Sending an email from Python using local Python SMTP server

15,629

Disclaimer

I expect that at least some of the information below will be redundant for you. Please bear with me. =)

smtplib vs. smptd

Python comes with two modules for dealing with email — smtplib and smtpd. The difference between the two is that smtplib is used to send emails, while smptd is used to receive emails. In this case, for sending emails, you should only need need to use smtplib.

Email with Python 3.6 smtplib

I want to send an email via my domain name (for example [email protected]).

Since you haven't provided your source script, I have listed a working Python 3.6 mail script for reference below:

# Python mail script with smtplib, email.utils and email.mime.text.

# --- imports ---

import smtplib
import email.utils
from email.mime.text import MIMEText

# --- create our message ---

# Create our message. 
msg = MIMEText('The body of your message.')
msg['To'] = email.utils.formataddr(('Recipient Name', '[email protected]'))
msg['From'] = email.utils.formataddr(('Your Name', '[email protected]'))
msg['Subject'] = 'Your Subject'

# --- send the email ---

# SMTP() is used with normal, unencrypted (non-SSL) email.
# To send email via an SSL connection, use SMTP_SSL().
server = smtplib.SMTP()

# Specifying an empty server.connect() statement defaults to ('localhost', 25).
# Therefore, we specify which mail server we wish to connect to.
server.connect ('mail.example.com', 25)

# Optional login for the receiving mail_server.
# server.login ('[email protected]', 'Password')

# Dump communication with the receiving server straight to to the console.
# server.set_debuglevel(True)  

# '[email protected]' is our envelope address and specifies the return
# path for bounced emails.
try:
    server.sendmail('[email protected]', ['[email protected]'], msg.as_string())
finally:
    server.quit()

Note that while I use "server" as the smtplib object name, you are free to continue use "s" (or whatever) in your own script. Likewise, use of the email.util and email.mime modules is not strictly necessary but they are helpful with constructing the final message.

I am new to SMTP and all I've been getting are lots of errors.

I can't say what your other errors might be caused by but the output you listed indicates a connection to sigsmileyface.ddns.net could not be established on port 25. The key lines are:

  • s = smtplib.SMTP('sigsmileyface.ddns.net'), which defaults to port 25.

  • The final line ConnectionRefusedError: [...] the target machine actively refused it, which could indicate a firewall or mail server configuration issue.

Troubleshooting

Check The Mail Server And Port

Establish that the server you are connecting to has an active mail server and what port it is running on (usually port 25 for incoming mail).

In your case, if you have control of sigsmileyface.ddns.net and are attempting to send emails to it, you should check that your mail server is set up correctly to receive mail on port 25. I believe that sendmail is the standard mail server on Pi. You should also confirm that the port isn't blocked by a firewall and that any necessary port forwarding is set up correctly in your router.

On a similar note, while it shouldn't really make a difference for directly connecting to your mail server, you may want to set up MX records if you are going to be sending mail to/receiving email at sigsmileyface.ddns.net.

Check Your Connection

You should double-check that your script has the correct connection values, whether you specify them in the smptlib object or via .connect(). Note that the host name you specify will always either be a direct connection to the server you wish to send mail to or an intermediary mail server (local or otherwise) you expect to pass messages on your behalf.

While it seems unlikely in your case, you should also be aware of any username or passwords needed to connect to the receiving server. This is most common when using another server to relay mail but it is worth remembering.

Check If You Need To Use A Relay

Ensure that you don't need to use a relay of some sort. In short, some ISPs do certain things to prevent spam that may necessitate the use of special mail servers to initially transfer or receive messages on port 25.

For instance, the local ISP for my home service filters port 25. It forces normal outgoing mail destined for this port to be sent via an ISP SSL mail relay. Simultaneously, it blocks incoming messages on this port for home users.

This means that to send and receive email on port 25, I have to pass normal outgoing mail (what your script is attempting) to smtp.isp.com to forward it to the recipient on port 25 while using a second (third-party) service to route incoming mail from port 25 to port XXX (where my mail server actually listens).

Note that doesn't actually prevent mail from being sent or received on other open ports (which can be fine for testing or personal uses) but since most mail servers use port 25 for consistency, using a relay may be a necessity in the long run.


In case it wasn't clear enough, you can do testing on ports other than 25 assuming you put the correct values in your script and have control of the receiving mail server.


Share:
15,629

Related videos on Youtube

Josua Robson
Author by

Josua Robson

Updated on September 18, 2022

Comments

  • Josua Robson
    Josua Robson over 1 year

    I have a server running Raspbian Jessie from which I want to send emails using Python. I have seen two modules that might work including smtpd and smtplib.

    I've seen lots of examples, some including smtp.gmail.com and localhost. I want to send an email with a specific domain name, for example: [email protected] I am new to SMTP and all I've been getting is lots of errors. How would I build the SMTP server code to actually send the email?

    Traceback (most recent call last):
      File "C:\Users\Josua\Desktop\smtp_test.py", line 42, in <module>
        s = smtplib.SMTP('sigsmileyface.ddns.net')
      File "C:\Users\Josua\AppData\Local\Programs\Python\Python36\lib\smtplib.py", line 251, in __init__
        (code, msg) = self.connect(host, port)
      File "C:\Users\Josua\AppData\Local\Programs\Python\Python36\lib\smtplib.py", line 336, in connect
        self.sock = self._get_socket(host, port, self.timeout)
      File "C:\Users\Josua\AppData\Local\Programs\Python\Python36\lib\smtplib.py", line 307, in _get_socket
        self.source_address)
      File "C:\Users\Josua\AppData\Local\Programs\Python\Python36\lib\socket.py", line 724, in create_connection
        raise err
      File "C:\Users\Josua\AppData\Local\Programs\Python\Python36\lib\socket.py", line 713, in create_connection
        sock.connect(sa)
    ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
    
    • Seth
      Seth about 6 years
      First of all you need to have a mailserver in place and credentials for it. In the next step you supply that information to the corresponding functions. Do you actually have a mail server running on sigsmileyface.ddns.net? The error is telling you that it's not listening to the port you tried to access. So its likely that you either have firewall that denies the conneciton or you simply don't have a mail server setup.