0

I use AWS SES to send emails from my instance - it works when I send just messages, but when files are attached to emails, it could not send and just gets pending.

It works when I do it from a local system, but from AWS. I'm wondering what happens when a file is attached to an email - is there somethings in AWS blocking it - or I need to use something different from smptlib of email?

I use the script below:

subject = 'xx'
body = "xx"
sender_email = "xx@gmail.com" `#this email address is confirmed in aws`
user = "xxxxx"  #ses username  

receiver_email = 'xxx@gmail.com' `#this email address is confirmed in aws`
password = 'xxxxx' # ses password   

message = MIMEMultipart()
message["From"] = formataddr(('name', 'xxx@gmail.com'))
message["To"] = receiver_email
message["Subject"] = subject    
# Add attachment to message and convert message to string
message.attach(MIMEText(body, "plain"))    
filename =  'sdf.txt' #the file that will be sent.    
   
with open(filename, "rb") as attachment:
    ## Add file as application/octet-stream
    # Email client can usually download this automatically as attachment

    part = MIMEBase("application", "octet-stream")
    part.set_payload(attachment.read())

# Encode file in ASCII characters to send by email   
encoders.encode_base64(part)   
   
part.add_header(
    "Content-Disposition",
    f"attachment; filename= {filename}",
)    

message.attach(part)
text = message.as_string()    
   
# Log in to server using secure context and send email
context = ssl.create_default_context()
try:
    with smtplib.SMTP_SSL("email-smtp.us-east-1.amazonaws.com", 465, context=context  ) as server:
        server.login(user, password)
        server.sendmail(sender_email, receiver_email, text)
        server.close()
except smtplib.SMTPException as e:
        print("Error: ", e)    
Berk
  • 263
  • 1
  • 14
  • 2
    As an aside. it looks like your `email` code was written for an older Python version. The `email` module in the standard library was overhauled in Python 3.6 to be more logical, versatile, and succinct; new code should target the (no longer very) new `EmailMessage` API. Probably throw away this code and start over with modern code from [the Python `email` examples documentation.](https://docs.python.org/3/library/email.examples.html) – tripleee Mar 12 '22 at 13:29
  • 2
    The space after `filename=` looks wrong. But replacing the legacy code with a modern version will significantly simplify it, and remove the need for you to do these things yourself. There may well be other spots in the code with similar mistakes. – tripleee Mar 12 '22 at 13:32
  • 1
    The point is that this script works when run in local system with/without attachments - but when it is run in AWS it works just with no attachments. – Berk Mar 12 '22 at 13:36
  • 2
    I can speculate on why that is, but the simple and straightforward solution is to replace your code with less error-prone version. – tripleee Mar 12 '22 at 13:38
  • Code aside, @Berk what do you mean "run inside AWS"? Ran where? Inside EC2? Lambda? Does the thing running it have access to the internet? Do the regular emails still work from AWS and it's just the ones with attachments not sending? Are you sure you have access to the attachment file on whatever you're running this one? – Ermiya Eskandary Mar 12 '22 at 19:08

1 Answers1

1

I modified the script, below - now it works nicely either with/without attachments in aws.

msg = MIMEMultipart()
body_part = MIMEText('xxxx', 'plain')
msg['Subject'] = 'xxx'
msg['From'] = formataddr(('xxxx', 'xxx@gmail.com'))
msg['To'] = 'xxx@gmail.com'
# Add body to email
msg.attach(body_part)
# open and read the file in binary
with open(path ,'rb') as file:
# Attach the file with filename to the email
    msg.attach(MIMEApplication(file.read(), Name='xxx'))
# Create SMTP object
smtp_obj = smtplib.SMTP_SSL("email-smtp.us-east-1.amazonaws.com", 465)
# Login to the server
user = "xxx"
# Replace smtp_password with your Amazon SES SMTP password.
password = 'xxx'
smtp_obj.login(user, password)
# Convert the message to a string and send it
smtp_obj.sendmail(msg['From'], msg['To'], msg.as_string())
smtp_obj.quit()
Berk
  • 263
  • 1
  • 14