Python - Sending Email



An application that handles and delivers e-mail over the Internet is called a "mail server". Simple Mail Transfer Protocol (SMTP) is a protocol, which handles sending an e-mail and routing e-mail between mail servers. It is an Internet standard for email transmission.

Python provides smtplib module, which defines an SMTP client session object that can be used to send mails to any Internet machine with an SMTP or ESMTP listener daemon.

smptlib.SMTP() Function

To send an email, you need to obtain the object of SMTP class with the following function −

import smtplib

smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )

Here is the detail of the parameters −

  • host − This is the host running your SMTP server. You can specifiy IP address of the host or a domain name like tutorialspoint.com. This is an optional argument.

  • port − If you are providing host argument, then you need to specify a port, where SMTP server is listening. Usually this port would be 25.

  • local_hostname − If your SMTP server is running on your local machine, then you can specify just localhost as the option.

The SMTP object has following methods −

  • connect(host, port, source_address) − This method establishes connection to a host on a given port.

  • login(user, password) − Log in on an SMTP server that requires authentication.

  • quit() − terminate the SMTP session.

  • data(msg) − sends message data to server.

  • docmd(cmd, args) − send a command, and return its response code.

  • ehlo(name) − Hostname to identify itself.

  • starttls() − puts the connection to the SMTP server into TLS mode.

  • getreply() −get a reply from the server consisting of server response code.

  • putcmd(cmd, args) − sends a command to the server.

  • send_message(msg, from_addr, to_addrs) − converts message to a bytestring and passes it to sendmail.

The smtpd Module

The smtpd module that comes pre-installed with Python has a local SMTP debugging server. You can test email functionality by starting it. It doesn't actually send emails to the specified address, it discards them and prints their content to the console. Running a local debugging server means it's not necessary to deal with encryption of messages or use credentials to log in to an email server.

You can start a local SMTP debugging server by typing the following in Command Prompt −

python -m smtpd -c DebuggingServer -n localhost:1025

Example

The following program sends a dummy email with the help of smtplib functionality.

import smtplib

def prompt(prompt):
   return input(prompt).strip()
   
fromaddr = prompt("From: ")
toaddrs = prompt("To: ").split()
print("Enter message, end with ^D (Unix) or ^Z (Windows):")

# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
   % (fromaddr, ", ".join(toaddrs)))
while True:
   try:
      line = input()
   except EOFError:
      break
   if not line:
      break
   msg = msg + line
   
print("Message length is", len(msg))
server = smtplib.SMTP('localhost', 1025)
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

Basically we use the sendmail() method, specifying three parameters −

  • The sender − A string with the address of the sender.

  • TheThe receivers − A list of strings, one for each recipient.

  • TheThe message − A message as a string formatted as specified in the various RFCs.

We have already started the SMTP debugging server. Run this program. User is asked to input the sender's ID, recipients and the message.

python example.py
From: abc@xyz.com
To: xyz@abc.com
Enter message, end with ^D (Unix) or ^Z (Windows):
Hello World
^Z

The console reflects the following log −

From: abc@xyz.com
reply: retcode (250); Msg: b'OK'
send: 'rcpt TO:<xyz@abc.com>\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
send: 'data\r\n'
reply: b'354 End data with <CR><LF>.<CR><LF>\r\n'
reply: retcode (354); Msg: b'End data with <CR><LF>.<CR><LF>'
data: (354, b'End data with <CR><LF>.<CR><LF>')
send: b'From: abc@xyz.com\r\nTo: xyz@abc.com\r\n\r\nHello
World\r\n.\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
data: (250, b'OK')
send: 'quit\r\n'
reply: b'221 Bye\r\n'
reply: retcode (221); Msg: b'Bye'

The terminal in which the SMTPD server is running shows this output

---------- MESSAGE FOLLOWS ----------
b'From: abc@xyz.com'
b'To: xyz@abc.com'
b'X-Peer: ::1'
b''
b'Hello World'
------------ END MESSAGE ------------

Using gmail SMTP

Let us look at the script below which uses Google's smtp mail server to send an email message.

First of all SMTP object is set up using gmail's smtp server and port 527. The SMTP object then identifies itself by invoking ehlo() command. We also activate Transport Layer Security to the outgoing mail message.

Next the login() command is invoked by passing credentials as arguments to it. Finally the mail message is assembled by attaching it a header in prescribed format and it is sent using sendmail() method. The SMTP object is closed afterwards.

import smtplib
content="Hello World"
mail=smtplib.SMTP('smtp.gmail.com', 587)
mail.ehlo()
mail.starttls()
sender='mvl@gmail.com'
recipient='tester@gmail.com'
mail.login('mvl@gmail.com','******')
header='To:'+receipient+'\n'+'From:' \
+sender+'\n'+'subject:testmail\n'
content=header+content
mail.sendmail(sender, recipient, content)
mail.close()

Before running above script, sender's gmail account must be configured to allow 'less secure apps'. Visit following link.

https://myaccount.google.com/lesssecureapps Set the shown toggle button to ON.

toggle button

If everything goes well, execute the above script. The message should be delivered to the recipient's inbox.

Advertisements