Search code examples
smtpencodenonetype

sending email thru smtp, gives 'NoneType' object has no attribute 'encode'


This is my code:

import os
from email.message import EmailMessage
import ssl
import smtplib


smtp_server = "smtp.office365.com"
port = 587  # For starttls
sender_email = "sender@mail.com"
email_receiver = 'receiver@mail.com'
password = os.environ.get("EMAIL_PASSWORD")
subject = "Hello"
body = """
Can you make it today?
"""
em = EmailMessage()
em['From'] = sender_email
em['To'] = email_receiver
em['Subject'] = subject
em.set_content(body)

# Create a secure SSL context
context = ssl.create_default_context()

# Try to log in to server and send email
try:
    server = smtplib.SMTP(smtp_server,port)
    server.ehlo() 
    server.starttls(context=context) # Secure the connection
    server.ehlo() 
    server.login(sender_email, password)
    
    server.sendmail('sender@mail.com', 'receiver@mail.com', em.as_string())
   
    print('Mail sent')
except Exception as e:
    # Print any error messages to stdout
    print(e)
finally:
    server.quit()

I get this error:

'NoneType' object has no attribute 'encode'

Where is my mistake?

Tried searching for 'NoneType' object has no attribute 'encode' but couldn't relate other answers to my code.


Solution

  • You are mixing up your ssl stuff. You either connect on the unencrypted default SMTP port 25 and then use the STARTTLS command to switch to an encrypted connection, OR you connect with a tls connection on port 465 and then you don't send the STARTTLS. The later is done using a SMTP_SSL object rather than the plain SMTP.

    That said, I don't see where exactly the encode came from; probably from the bowels of the SMTP library.

    This works for me:

    import os
    from email.message import EmailMessage
    import ssl
    import smtplib
    
    smtp_server = "smtp.office365.com"
    port = 25 # plain connection, we'll switch to tls later with starttls
    sender_email = 'me@example.org'
    email_receiver = sender_email
    password = os.environ.get("EMAIL_PASSWORD")
    em = EmailMessage()
    em['From'] = sender_email
    em['To'] = email_receiver
    em['Subject'] = "Hello"
    em.set_content("Can you make it today?")
    
    # Create a secure SSL context
    context = ssl.create_default_context()
    
    # Try to log in to server and send email
    with smtplib.SMTP(smtp_server, port) as server:
        server.ehlo()
        server.starttls(context=context) # Secure the connection
        server.ehlo()
        server.login(sender_email, password)
        server.sendmail(sender_email, email_receiver, em.as_string())
    print('Mail sent')
    

    I've used a with block so that the connection gets closed automatically. I also removed the except so that I get a full stack trace of any exception instead of just printing an error message. I've shortened some of your original variables for brevity.