Giter VIP home page Giter VIP logo

uber-code-challenge's Introduction

Readme

I chose the Email Service project and the back-end track.

Technical Choices

  • Written in Python 2
  • Uses Flask for the HTTP server
    • Flask was chosen for its light weight and ease of use
  • Configuration files are written in yaml, using PyYAML for loading
  • The requests library is used for all HTTP requests, as urllib2 is just sad.
  • gunicorn is used to interface between the application and the internet. In a more serious production environment, gunicorn should be behind an nginx proxy.
  • In order to make the service flexible and modular, the connections to the mail servers are loaded dynamically. When the server starts up, the config file is processed. Each service listed contains a settings dictionary (to allow multiple instances of the same service to coexist. Multiple mailgun accounts, perhaps), as well as a module name.

Service Configuration

The config/mail.yml file looks as follows:

drivers:
  - name: "Human-readable service name."
    module: "module_name"
    settings:
      setting1: "value1"
      setting2: "value2"
  - name: "Human-readable service name 2."
    module: "module_name2"
    settings:
      setting1: "value1"
      setting2: "value2"

module refers to a python module that should be inside of the package uberemails.mail_drivers. The settings dictionary is passed directly to the driver's constructor as **kwargs

Presently, modifications to the config file requires a restart of the server.

Mail Driver

All mail drivers inherit from uberemail.mail_drivers.mailer.Mailer. There is one method to be overridden when new drivers are added. _sendmail(self,**kwargs) is called from Mailer when mail is to be sent. It expects the following args to be passd in:

  • sender: email address of the sender
  • to: email address of the recipient or a list of email addresses.
  • subject: subject line of the email
  • text: textual body of the email

It also recognizes the following optional arguments:

  • cc, bcc: email address(es). May be a single email or a list of emails.
  • attachments: Files to be attached. This should be a list of dictionaries. Each dictionary has the following keys:
    • filename: filename of the attachment
    • data: data for the attachment. May be either a string or a file-like object.
    • mimetype: mimetype of the attachment.

If the mail is sent successfully, then _sendmail is to return True. If the service is not currently available/working, _sendmail is to return False. If the service reports that the data is invalid, _sendmail is to raise a MailError.

MailError

MailError is the exception class used to signal various errors and propagate them back to the API's response. It lives in uberemail.exceptions and has a few error codes that get passed back to the user in the response JSON.

Sending Emails

Emails can be sent with the service by sending a POST request containing JSON to /send. The Content-Type should be set to application/json. The service also tentatively accepts multipart/form-data and application/x-www-form-urlencoded content types, but these are presently unreliable.

The JSON message sent to the server should look like this:

{
  sender: "[email protected]",
  to: "[email protected]",
  subject: "Subject line",
  text: "Body of the email..."
}

It also optionally supports cc, bcc, and attachments. Once again, to, cc, and bcc support multiple addresses. attachments is a list of dictionaries. The only required entry is the data, which is to be a base-64 encoded string.

{
  sender: "[email protected]",
  to: "[email protected]",
  bc: ["[email protected]", "[email protected]"],
  bcc: ["[email protected]"],
  subject: "Subject line",
  text: "Body of the email..."
  attachments: [
    {
      filename: "filename"
      data: "base64-encoded data",
      mimetype: "mimetype"
    },
    {
      data: "base64-encoded data 2"
    }
  ]
}

If using multipart/form-data or application/x-www-form-urlencoded, to, cc, and bcc may be either a comma-separated list of email addresses or appear multiple times in the form data.

Testing

Testing is done by running tests.py in the main directory. It will launch and control gunicorn using the start_gunicorn, stop_gunicorn, and restart_gunicorn scripts.

Currently the testing code is very repetitive. It needs to be reworked such that one can just add functions that get called instead of manually writing each test.

Additional Thoughts

Things that should be changed if I were to spend more time on this:

  • Be more responsive to changes to the configuration. Possibly change to loading all .yml files in the config/ folder.
  • Improve testing code
  • Fix the wonkiness in application/x-www-form-urlencode and multipart/form-data code

Resume

My resume can be found here

My github is @wtlangford

uber-code-challenge's People

Contributors

wtlangford avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.