Package: py-basic-ses
py-basic-sespy-basic-ses provides a command line application and library to send emails via Amazon Web Services' Simple Email Service, or AWS SES, API by leveraging the boto3 library.This package requiresLinux or WindowsPython 3.8, 3.9, 3.10, 3.11, or 3.12Dependencies that will install with this package:boto3 (and its dependencies)click (and its dependencies)AWS account with:SES setup correctlyAn IAM user with access to send email via SESAWS IAM credentials stored appropriately on the machine that is running this application/libraryHow to installUse the PIP package manager to install this application from pypi.org by running the following commandpip install py-basic-sesAWS SES OverviewAWS's Simple Email Service (SES) allows email to be sent from your custom domain without the hassle or barriers of setting up a mail server (I've tried this a couple of times, and it is a huge pain to do on a small scale). SES provides support for DKIM (helps your emails land in the inbox rather than the spam folder) and custom MAIL FROM address (the envelope sender/return path will be your domain rather than @us-west-2.amazonses.com).In order to use the py-basic-ses application or library, you do have to setup the SES service in your AWS account. You will need to obtain your IAM access ID and secret key, and set the appropriate policies. More information on setting up SES and retrieving your required credentials can be found in theSetting up SES, IAM users, and policiessection of this README.You can learn more about AWS SEShere.CredentialsIn order for the py-basic-ses command line application or library to work, you have to make your AWS IAM access ID and secret key available on the machine running py-basic-ses. Your access ID will look something likeBKIAYPKAJ70YPSLMJ9BZ, and your secret key will look something like7GRwZHFWy8DHpqNXZTgcvSaY/T9/nZ+6Xm1E9FxS.You have two options for storing your ID and secret key:Store your ID and secret key in the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY respectively.Create a file named credentials, without any extension, and save the following information in it:[default]
       aws_access_key_id = your-access-key-here
       aws_secret_access_key = your-secret-access-key-hereFor Windows, save your credentials file atC:\Users\<user name>\.aws\credentials. For Linux, save your credentials file at~/.aws/credentials.To get help retrieving your credentials, see theSetting up SES, IAM users, and policiessection of this README.Command line applicationWith py-basic-ses installed you will have two commands available from the terminal:send-testandsend-email.send-test --helpandsend-email --helpwill display the availale options with explanations.Below are examples of commands for sending a test email and sending a production email.Remember, you need to have your credentials stored properly on your machine. See theCredentialssection of this README for more details.Sending a test emailsend-test --to to-user@to-domain.com --fromaddr from-user@from-domain.com --awsregion your-aws-regionWhereyour-aws-regionis the region your SES service is operating in. An example would beus-west-2.Sending a production emailsend-email --to to-user@to-domain.com --fromaddr from-user@from-domain.com --fromname 'From User' --awsregion your-aws-region --subject 'Email Subject' --message_txt 'Email plain text message' --message_html '<h1>HTML Email Heading</h1><p>Email html message</p>'Whereyour-aws-regionis the region your SES service is operating in. An example would beus-west-2.Thesend-emailcommand will send a two part message with html as the primary email body, and a plain text alternative email body. If only--message_txtis provided, the plain text will be put in both the html and plain text sections of the email. Not all arguments are required. Run thesend-email --helpcommand to see the list of arguments, and whether they are required or optional.LibraryBelow is a code sample demonstrating how you would send an email using py-basic-ses. Remember, you need to have your credentials stored properly on your machine. See theCredentialssection of this README for more details.# import the SESSender class
from py_basic_ses.emailing import SESSender

def ses_send_email():
    to_email_address = "to-user@to-domain.com" 
    from_email_address = "from-user@from-domain.com"
    email_from_name = "From User"
    email_message_txt = "This is an awesome email message."
    email_message_html = "<h1>Awesome Email</h1><p>This is an awesome html formatted email.</p>"
    email_subject = "Awesome Subject"
    ses_aws_region = "us-west-2"


    # instantiate the SESSender object
    ses_send_obj = SESSender(sendto=to_email_address,           # Required
                            fromaddr=from_email_address,        # Required
                            fromname=email_from_name,           # Optional
                            message_txt=email_message_txt,      # Required
                            message_html=email_message_html,    # Optional
                            msgsubject=email_subject,           # Optional
                            aws_region=ses_aws_region)          # Required

    # send the email
    print("Attempting to send an email to {0}".format(to_email_address))
    msg_id = ses_send_obj.send_email()

    print(f"MsgID: {msg_id}")
    

if __name__ == "__main__":
    ses_send_email()ExceptionsBelow is a list of anticipated exceptions for theSESSender.send_email()method which are handled in the CLI tool, but would need to be handled in a try/except block in your code.OSError: Occurs when the operating system is not Linux or Windowspy_basic_ses.exceptions.CredError: Expected when there is a problem with the location or format of the AWS SES credentialsbotocore.exceptions.ClientError: Raised if there is an issue with the AWS boto3 client.The exception object contains an error message in itsresponseattribute which can be acceses like this, assumingeis an instance of theClientError:ClientError.response['Error']['Message']Dev and testingInstall for devpy-basic-ses has addiitonal dependencies when installed for dev. To install the package for development, clone the repository, move into the root of the project, and runpip install -e .[dev]. This will install themockandcoveragepackages for testing. The -e flag makes the package editable while installed. Note the lack of a space beetween the.. and[dev].Export environment variablesexport environment variables from .env file using bashexport $(grep -v '^#' .env | xargs)Testingpy-basic-ses utilizesunittestto run unit tests.unittestis not included in theextras_require =directive of setup.py, because it is included when Python 3 is installed. Thecoveragepackage allows us to track how much of our code is covered with tests.To run all of the unit tests contained in thetests/directory, move into the root of the project atpy-basic-ses/. Then, runcoverage run --source=src -m unittest discover -v -s tests/unit. This command will look for all of the modules starting withtest_in thetests/unitdirectory, and run them usingunittest.To see a report of test coverage, runcoverage report -m. A more nicely formatted report can be generated by runningcoverage html, then openinghtmlcov/index.htmlin a browser. For more information on using the coverage package seehttps://coverage.readthedocs.io/en/coverage-5.5.Setting up SES, IAM users, and policiesGetting all of your AWS services, users, and policies setup correctly to send emails via the SES API can be challenging the first time. Below are some notes to help get you going.Please, checkout Amazon'sdocsas well. They are much more detailed.At a high level, here is what needs to be done:Create an Amazon Web Services accountRegister your domain (AWS's Route 53 makes this pretty easy)SES setupVerify your domain by adding txt records to your DNS hosted zoneAmazon's verify domain instructionsSetup DKIM by adding three CNAME records to your DNS hosted zoneEnable your account for sending email - get out of the sandboxAmazon's get out of the sandbox instructionsIAM setupCreate a new userGet credentials - This is the access ID and secret key mentioned in theCredentialssection of this README.Create the proper policy for your IAM user to send emails from your SESBelow is each step with screen shots and more detailed instructions.Create an Amazon Web Services accountSorry, not going to walk you through this. Go to aws.amazon.com and register.Register your domainYou will need to own and control the domain you want to send email from. AWS offers registration and DNS services through their Route 53 offering. Just search for Route 53 once you are logged into the AWS mangement console. You can also register your domain from another registrar, but it is convenient to have everything under one account. Also, AWS DNS entries propogate very quickly, like in a couple of minutes. I have had to wait for up to 20 - 30 minutes with another registrar.SES SetupAfter logging into the AWS management console. Type 'SES' into the search bar in the top nav bar, and click on Amazon Simple Email Service.Once you are in the SES Management Console (you will see SES Home at the top of the left navigation panel), you will need to select the region you want your SES service to operate in. Each region reprsents an AWS data center's geogrphic location. Notice the labels next to each geographic description: us-east-1, us-east-2, us-west-1, and so on. These are the region identifyers that will need to be provided to the py-basic-ses command line application and library, so take note of which one you choose.Click on Domains in the left nav panel.Click Verify a New DomainEnter your domain (can be a subdomain), check the box next to Generate DKIM Settings, and click Verify This Domain.You will see the TXT DNS record you need to add to your domain to verify that you own it. If you used Route 53 to register your domain, go into your domain's hosted zone and add the TXT record.You will also see three CNAME records that are needed for DKIM. There are three. Be sure to scoll in the DKIM section. Again, if you used Route 53, add these CNAME records to your domain's hosted zone.After closing the modal with the verification information, you will see your domain listed in the SES Management Console with pending verification next to it. It will take a few minutes for SES to recognize the TXT and DKIM records you just added. Once your domain is verified, you will see 'verified' in green next to your domain.Being verified isn't enough. SES puts all new SES accounts in the Amazon SES sandbox. This means you can only send to verified email addresses and domains, and from verified email addresses and domains. This might be fine if you just want to email yourself, but if you need to send to other domains and email addresses outside of your control, you will want to get out of the sandbox. You can read the documentation from Amazonhere.IAM setupIAM stands for Identity and Access Management. With the IAM Mangement Console you can create users, grant them access to APIs, and even allow them to log in to the AWS Mangement console.Before we create our new user, we need to take note of the ARN, or Amazon Resource Name of our domain in SES. Amazon identifies each resource with a unique identifyer - its ARN. We will need this in order to create the policy for our user later. To see the ARN for your domain in SES, click on the domain.Search for IAM in the top nav bar, and click IAM.Click the Users link in the left nav panel.Click Add User.Enter your user name and select the check box next to Programmatic Access. Obviously, fill in the user you want, not the one in the screen shot.Click Next: Tags without setting up any permissions. We will handle permissions later. Then click Next: Review without adding tags. Finally, click Create User. You will see a one-time only screen to collect your credentials. DO NOT CLICK CLOSE until you have stored your Access Key ID and Secret access key.You will now add the permissions required for the user you just made to send emails from the domain you setup in SES. Click on Users in the left nav panel. Then, click on the user you just made. Under Permissions policies, click Add inline policy.In the Create Policy, click the JSON tab. Copy and paste the example SES policy json below into the json editor. Change the ARN listed after"Resource":to the ARN of your domain in SES. Also, change the value after"ses:FromAddress":to whatever email you want to limit your new IAM user to when indicating the email from address. You can remove this restriction, and allow the user to send from any email by removing the entire"Condition":object and its sub-objects from the JSON editor. There are many other permissions that could be added to the"Action":object, but this policy just allows the user to send emails and raw emails.Example SES policy json{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "uniquestring",
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail",
                "ses:SendRawEmail"
            ],
            "Resource": "arn:aws:ses:us-west-2:580492328624:identity/py-basic-ses.domain.com",
            "Condition": {
                "StringEquals": {
                    "ses:FromAddress": "from-user@py-basic-ses.domain.com"
                }
            }
        }
    ]
}Click Next without adding tags. Finally, enter a name for your policy, and click create policy.That should be it. Your user should now be able to send email using the SES API for your domain.Release notesv0.1.2Added support for python 3.10Added a .gitlab-ci.yml file for automated testing and publishingv0.1.3Added python 3.10 programming language classifier to setup.pyv1.1.1Added support for python 3.11v2.0.0Refactored to remove unnecessary print statements and raise useful exceptions.