Skip to content
This repository has been archived by the owner on Jul 6, 2022. It is now read-only.

Commit

Permalink
Merge branch 'library_transformation'
Browse files Browse the repository at this point in the history
  • Loading branch information
hbayindir committed Apr 25, 2018
2 parents 2835c89 + 2f207d6 commit 6c0fa19
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 74 deletions.
17 changes: 17 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>railgun</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
5 changes: 5 additions & 0 deletions .pydevproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Python 3</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.6</pydev_property>
</pydev_project>
2 changes: 2 additions & 0 deletions .settings/org.eclipse.core.resources.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding//src/railgun.py=utf-8
156 changes: 82 additions & 74 deletions src/railgun.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,41 +35,82 @@


# Some global constants. Change as you see fit.
CONFIGURATION_FILE_PATH = '../conf/railgun.conf'
DEFAULT_CONFIGURATION_FILE_PATH = '../conf/railgun.conf'
LOGGING_LEVEL = logging.WARN

# Below are mailgun configuation options.
# Its modeled as a nested dictionary intentionally.
# Only these keys will be queried from the file.
# First, the logging options.
railgunOptions = dict ()
railgunOptions['logging'] = dict()
railgunOptions['logging']['log_file_path'] = None

# MailGun API options.
railgunOptions['mailgun_api'] = dict()
railgunOptions['mailgun_api']['base_uri'] = None
railgunOptions['mailgun_api']['api_key'] = None

# MailGun API sender options.
railgunOptions['sender'] = dict()
railgunOptions['sender']['name'] = None
railgunOptions['sender']['email_address'] = None
# This is our new Railgun class, which allows the application to be used as a library too.
class Railgun:

# Let's put a small constructor here.
def __init__ (self, configurationFilePath = DEFAULT_CONFIGURATION_FILE_PATH):
# Root dictionary.
self.options = dict ()

# Logging options.
self.options['logging'] = dict ()
self.options['logging']['log_file_path'] = None

# Mailgun API options.
self.options['mailgun_api'] = dict()
self.options['mailgun_api']['base_uri'] = None
self.options['mailgun_api']['api_key'] = None

# Mailgun API sender options.
self.options['sender'] = dict()
self.options['sender']['name'] = None
self.options['sender']['email_address'] = None

# Mail recipient (one for now)
self.options['recipients'] = dict()
self.options['recipients']['email_address'] = None

# Parse the configuration file here.
self.__parseConfigurationFile(configurationFilePath)
self.__checkConfigurationSanity()

def __parseConfigurationFile(self, configurationFilePath):
# Let's read this little file.
self.configuration = configparser.ConfigParser ()
self.configuration.read(DEFAULT_CONFIGURATION_FILE_PATH)

# These loops iterate over the configuration options.
# This method is implemented to prevent code from attacks.
for sectionKey in self.options.keys ():
for optionKey in self.options[sectionKey].keys ():
try:
self.options[sectionKey][optionKey] = self.configuration[sectionKey][optionKey]
# Handle missing keys gracefully here.
except KeyError as exception:
pass

# This function checks whether the minimum requirements for railgun configuration is met.
def __checkConfigurationSanity (self):

# Mail recipient (one for now)
railgunOptions['recipients'] = dict()
railgunOptions['recipients']['email_address'] = None
if self.options['mailgun_api']['base_uri'] == None:
raise Exception ('base_uri value of [mailgun_api] section cannot be None or missing. Please obtain the value for your domain from Mail Gun dashboard.')

if self.options['mailgun_api']['api_key'] == None:
raise Exception ('api_key value of [mailgun_api] section cannot be None or missing. Please obtain the value for your domain from Mail Gun dashboard.')

if self.options['sender']['name'] == None:
raise Exception ('name value of [sender] section cannot be None or missing. Please fill this value with a descriptive name for the sender.')

if self.options['sender']['email_address'] == None:
raise Exception ('email_address value of [sender] section cannot be None or missing. Please fill this value with a descriptive email address for the sender.')

if self.options['recipients']['email_address'] == None:
raise Exception ('email_address value of [recipients] section cannot be None or missing. Please fill this value with the email address for the intended receiver of the email.')


def sendSimpleMessage(subject, body):
def sendTextEmail(subject, body, configuration):

mailSender = railgunOptions['sender']['name'] + ' <' + railgunOptions['sender']['email_address'] + '>'
mailSender = configuration['sender']['name'] + ' <' + configuration['sender']['email_address'] + '>'

return requests.post(
railgunOptions['mailgun_api']['base_uri'] + '/messages',
auth=('api', railgunOptions['mailgun_api']['api_key']),
configuration['mailgun_api']['base_uri'] + '/messages',
auth=('api', configuration['mailgun_api']['api_key']),
data={'from': mailSender,
'to': railgunOptions['recipients']['email_address'],
'to': configuration['recipients']['email_address'],
'subject': subject,
'text': body})

Expand All @@ -78,23 +119,17 @@ def sendSimpleMessage(subject, body):

# Let's start with parsing the configuration file.
# Check the file's existence first.
if os.path.isfile(CONFIGURATION_FILE_PATH) == False:
print ('FATAL: Configuration file ' + CONFIGURATION_FILE_PATH + ' is not present, exiting.', file = sys.stderr)
if os.path.isfile(DEFAULT_CONFIGURATION_FILE_PATH) == False:
print ('FATAL: Configuration file ' + DEFAULT_CONFIGURATION_FILE_PATH + ' is not present, exiting.', file = sys.stderr)
sys.exit (1)

# Let's read this little file.
configuration = configparser.ConfigParser ()
configuration.read(CONFIGURATION_FILE_PATH)

# These loops iterate over the configuration options.
# This method is implemented to prevent code from attacks.
for sectionKey in railgunOptions.keys ():
for optionKey in railgunOptions[sectionKey].keys ():
try:
railgunOptions[sectionKey][optionKey] = configuration[sectionKey][optionKey]
# Handle missing keys gracefully here.
except KeyError as exception:
pass
try:
railgun = Railgun ()
except Exception as exception:
print ('An exception has ocurred: ' + str(exception), file=sys.stderr)
print ('Please correct above errors and restart railgun.', file=sys.stderr)
sys.exit(1)


# Let's parse some arguments.
argumentParser = argparse.ArgumentParser()
Expand All @@ -107,7 +142,7 @@ def sendSimpleMessage(subject, body):
verbosityGroup.add_argument ('-q', '--quiet', help = 'Do not print anything to console (overrides verbose).', action = 'store_true')

# Version always comes last.
argumentParser.add_argument ('-V', '--version', help = 'Print ' + argumentParser.prog + ' version and exit.', action = 'version', version = argumentParser.prog + ' version 1.0.1')
argumentParser.add_argument ('-V', '--version', help = 'Print ' + argumentParser.prog + ' version and exit.', action = 'version', version = argumentParser.prog + ' version 1.0.3')

arguments = argumentParser.parse_args()

Expand All @@ -123,7 +158,7 @@ def sendSimpleMessage(subject, body):

# Let's set the logger up.
try:
logging.basicConfig(filename = railgunOptions['logging']['log_file_path'], level = LOGGING_LEVEL, format = '%(levelname)s: %(message)s')
logging.basicConfig(filename = railgun.options['logging']['log_file_path'], level = LOGGING_LEVEL, format = '%(levelname)s: %(message)s')

# Get the local logger and start.
localLogger = logging.getLogger('main')
Expand All @@ -138,41 +173,14 @@ def sendSimpleMessage(subject, body):
print ('Something about disk I/O went bad: ' + str(exception), file = sys.stderr)
sys.exit(1)

# Let's make configuration sanity check. Some configuration options are mandatory. We cannot continue without them.
isConfigurationSane = True

if railgunOptions['mailgun_api']['base_uri'] == None:
localLogger.critical ('base_uri value of [mailgun_api] section cannot be None or missing. Please obtain the value for your domain from Mail Gun dashboard.')
isConfigurationSane = False

if railgunOptions['mailgun_api']['api_key'] == None:
localLogger.critical ('api_key value of [mailgun_api] section cannot be None or missing. Please obtain the value for your domain from Mail Gun dashboard.')
isConfigurationSane = False

if railgunOptions['sender']['name'] == None:
localLogger.critical ('name value of [sender] section cannot be None or missing. Please fill this value with a descriptive name for the sender.')
isConfigurationSane = False

if railgunOptions['sender']['email_address'] == None:
localLogger.critical ('email_address value of [sender] section cannot be None or missing. Please fill this value with a descriptive email address for the sender.')
isConfigurationSane = False

if railgunOptions['recipients']['email_address'] == None:
localLogger.critical ('email_address value of [recipients] section cannot be None or missing. Please fill this value with the email address for the intended receiver of the email.')
isConfigurationSane = False

if isConfigurationSane == False:
localLogger.critical ('Please correct the configuration errors above and restart ' + sys.argv[0])
sys.exit (1)

# Let's write some debugging information
localLogger.debug ('Configuarion details:')
localLogger.debug ('Logging file path: ' + str(railgunOptions['logging']['log_file_path']) + '.')
localLogger.debug ('Sending mails as: ' + str(railgunOptions['sender']['name']) + ' <' + str(railgunOptions['sender']['email_address']) + '>.')
localLogger.debug ('Sending mails to: ' + str(railgunOptions['recipients']['email_address']) + '.')
localLogger.debug ('Logging file path: ' + str(railgun.options['logging']['log_file_path']) + '.')
localLogger.debug ('Sending mails as: ' + str(railgun.options['sender']['name']) + ' <' + str(railgun.options['sender']['email_address']) + '>.')
localLogger.debug ('Sending mails to: ' + str(railgun.options['recipients']['email_address']) + '.')

# Setting up the application is complete. Just send the mail now.
request = sendSimpleMessage(arguments.subject, arguments.body)
request = sendTextEmail(arguments.subject, arguments.body, railgun.options)

if request.status_code == 200:
localLogger.info ('The message has sent successfully.')
Expand Down

0 comments on commit 6c0fa19

Please sign in to comment.