Search code examples
pythonamazon-web-servicesboto3amazon-ses

Amazon SES creds working with smtplib but not with boto3


I'm trying to send emails using Amazon SES. Created the roles and API keys and policies and tested it out using Python smtplib. Pasting the snippet below:

import smtplib

fromaddr = "some@email.com"
toaddrs  = "other@email.com"
msg = """From: some@email.com
Hello, this is test from python.
"""

smtp_server = 'email-smtp.us-east-1.amazonaws.com'
smtp_username = 'SES_KEY'
smtp_password = 'SES_SECRET'
smtp_port = '25'
smtp_do_tls = True

server = smtplib.SMTP(
    host = smtp_server,
    port = smtp_port,
    timeout = 10
)
server.set_debuglevel(10)
server.starttls()
server.ehlo()
server.login(smtp_username, smtp_password)
server.sendmail(fromaddr, toaddrs, msg)
print(server.quit())

It works as expected. I recieve the email and following output:

send: 'ehlo servername.com\r\n'
reply: '250-email-smtp.amazonaws.com\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-STARTTLS\r\n'
reply: '250-AUTH PLAIN LOGIN\r\n'
reply: '250 Ok\r\n'
reply: retcode (250); Msg: email-smtp.amazonaws.com
8BITMIME
STARTTLS
AUTH PLAIN LOGIN
Ok
send: 'AUTH PLAIN AEFLSU......HJiRkh3\r\n'
reply: '235 Authentication successful.\r\n'
reply: retcode (235); Msg: Authentication successful.
send: 'mail FROM:<some@email.com>\r\n'
reply: '250 Ok\r\n'
reply: retcode (250); Msg: Ok
send: 'rcpt TO:<other@email.com>\r\n'
reply: '250 Ok\r\n'
reply: retcode (250); Msg: Ok
send: 'data\r\n'
reply: '354 End data with <CR><LF>.<CR><LF>\r\n'
reply: retcode (354); Msg: End data with <CR><LF>.<CR><LF>
data: (354, 'End data with <CR><LF>.<CR><LF>')
send: 'From: some@email.com\r\n\r\nHello, this is test from python.\r\n.\r\n'
reply: '250 Ok 0100018a4b42947f-c2eed....96d8078-000000\r\n'
reply: retcode (250); Msg: Ok 0100018a4b429....52-e84d296d8078-000000
data: (250, 'Ok 0100018a4b42947f-......-e84d296d8078-000000')
send: 'quit\r\n'
reply: '221 Bye\r\n'
reply: retcode (221); Msg: Bye
(221, 'Bye')

But when I do the same thing with boto3, I'm getting an error:

Error: An error occurred (SignatureDoesNotMatch) when calling the SendEmail operation: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

Snippet:

import boto3
from botocore.exceptions import BotoCoreError, ClientError

def send_email():
    ses = boto3.client('ses', region_name='us-east-1', aws_access_key_id='key', aws_secret_access_key='secret')
    subject = 'Your Email Subject'
    body = """
    This is a test email from BOTO3 SES.
    """
    message = {"Subject": {"Data": subject},
               "Body": {"Text": {"Data": body}}}

    try:
        response = ses.send_email(Source='some@email.com',
                                  Destination={'ToAddresses': ['other@email.com']},
                                  Message=message)
    except (BotoCoreError, ClientError) as error:
        print(f"Error: {error}")
send_email()

Has anyone faced this issue before? I have created the identity in us-east-1, so I'm using that region, plus I have also tried giving the role full access to send email on all resources, but boto3 is still giving errors.

Any help is appreciated.


Solution

  • The SES credentials you created for sending emails over SMTP will only work for sending emails via the SMTP protocol, to the AWS SES SMTP endpoint.

    Per the official documentation:

    Important

    Your SMTP credentials aren't identical to your AWS access keys or the credentials that you use to sign in to the Amazon SES console.

    The Boto3 ses.send_email() function does not use the SMTP protocol, and it does not connect to the SMTP endpoint, it is directly calling the AWS SES API. You cannot use SMTP credentials to interface with the standard AWS API. The SES SMTP credentials are primarily for use with software that was built to interface with standard SMTP email servers, and has no support for the AWS API.

    You would need to use regular IAM credentials with Boto3.