All Products
Search
Document Center

Direct Mail:SMTP call example for Python 3.6 and later

Last Updated:Oct 29, 2025

This topic describes how to send emails using the Simple Mail Transfer Protocol (SMTP) in Python 3.6 or later.

Example code:

# -*- coding:utf-8 -*-
import smtplib
import email
# import json
# import base64
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# from email.mime.image import MIMEImage
# from email.mime.base import MIMEBase
# from email.mime.application import MIMEApplication
from email.header import Header
from email.utils import formataddr
# import urllib.request
# import ssl

# The username, which is the sender address created in the console.
username = 'XXXXXXXX'
# The password, which is the SMTP password created in the console.
password = 'XXXXXXXX'
# The custom reply-to address. This is independent of the settings in the console. The Direct Mail sender address does not receive emails. When a recipient replies, the email is automatically sent to this reply-to address.
replyto = 'XXXXXXXX'
# The displayed 'To' recipient addresses.
rcptto = ['address1@example.net', 'address2@example.net']
# The displayed 'Cc' recipient addresses.
rcptcc = ['address3@example.net', 'address4@example.net']
# The 'Bcc' recipient addresses. Bcc recipients are not displayed on the email but can receive it.
rcptbcc = ['address5@example.net', 'address6@example.net']
# All recipient addresses, including Cc addresses. You cannot send an email to more than 60 recipients at a time.
receivers = rcptto + rcptcc + rcptbcc

# Build the 'alternative' structure.
msg = MIMEMultipart('alternative')
msg['Subject'] = Header('Custom email subject')
msg['From'] = formataddr(["Custom sender nickname", username])  # Nickname + sender address (or on-behalf-of address)
# Convert the list to a string.
msg['To'] = ",".join(rcptto)
msg['Cc'] = ",".join(rcptcc)
msg['Reply-to'] = replyto  # Used to receive reply emails. The recipient must support standard protocols.
msg['Return-Path'] = 'test@example.net'  # Used to receive bounce emails. The recipient must support standard protocols.
msg['Message-id'] = email.utils.make_msgid()  # The message-id uniquely identifies each email. Its format must comply with RFC 5322, typically like <uniquestring@example.com>. The 'uniquestring' is a unique identifier generated by the mail server and may contain information such as a timestamp and a random number.
msg['Date'] = email.utils.formatdate()

# To enable the email tracking service, use the following code to set the tracking link header.
# You must add a tag to the email. This tag must be created in the console. You can use the tag 10 minutes after it is created.
# Set the tracking link header.
# tagName = 'xxxxxxx'
#
# # The values for OpenTrace and LinkTrace are fixed as the string '1'.
# trace = {
#     "OpenTrace": '1',  # Enable email open tracking.
#     "LinkTrace": '1',  # Enable URL click tracking in the email.
#     "TagName": tagName  # The tag name created in the console.
# }
# jsonTrace = json.dumps(trace)
# base64Trace = str(base64.b64encode(jsonTrace.encode('utf-8')), 'utf-8')
# # print(base64Trace)
# msg.add_header("X-AliDM-Trace", base64Trace)


# Build the text/plain part of the 'alternative' structure.
# textplain = MIMEText('Custom plain text part', _subtype='plain', _charset='UTF-8')
# msg.attach(textplain)

# Build the text/html part of the 'alternative' structure.
texthtml = MIMEText('Custom HTML part', _subtype='html', _charset='UTF-8')
msg.attach(texthtml)

# # Send a local attachment.
# files = [r'C:\Users\Downloads\test1.jpg', r'C:\Users\Downloads\test2.jpg']
# for t in files:
#     filename = t.rsplit('/', 1)[1]
#     part_attach1 = MIMEApplication(open(t, 'rb').read())  # Open the attachment.
#     part_attach1.add_header('Content-Disposition', 'attachment', filename=filename)  # Name the attachment.
#     msg.attach(part_attach1)  # Add the attachment.

# # Send a URL attachment.
# files = [r'https://example.oss-cn-shanghai.aliyuncs.com/xxxxxxxxxxx.png']
# for t in files:
#     filename=t.rsplit('/', 1)[1]
#     response = urllib.request.urlopen(t)
#     part_attach1 = MIMEApplication(response.read())  # Open the attachment, which is not a local file.
#     part_attach1.add_header('Content-Disposition', 'attachment', filename=filename)  # Name the attachment.
#     msg.attach(part_attach1)  # Add the attachment.


# Send the email.
try:
    # To use SSL for encryption, create the client as follows.
    # client = smtplib.SMTP_SSL('smtpdm.aliyun.com', 465)
    
    # If an SSL handshake fails in Python 3.10 or 3.11, handle it as follows:
    # ctxt = ssl.create_default_context()
    # ctxt.set_ciphers('DEFAULT')
    # client = smtplib.SMTP_SSL('smtpdm.aliyun.com', 465, context=ctxt)
    
    
    # The standard SMTP port is 25 or 80.
    client = smtplib.SMTP('smtpdm.aliyun.com', 80)
    # Enable DEBUG mode.
    client.set_debuglevel(0)
    # The sender and the authentication address must be the same.
    client.login(username, password)
    # Note: To get the return value of the DATA command, see the sendmail encapsulation method of smtplib:
    # Use the SMTP.mail, SMTP.rcpt, and SMTP.data methods.
    # print(receivers)
    client.sendmail(username, receivers, msg.as_string())  # Multiple recipients are supported. For the specific limit, see the product specifications.
    client.quit()
    print('Email sent successfully!')
except smtplib.SMTPConnectError as e:
    print('Failed to send the email. Connection failed:', e.smtp_code, e.smtp_error)
except smtplib.SMTPAuthenticationError as e:
    print('Failed to send the email. Authentication error:', e.smtp_code, e.smtp_error)
except smtplib.SMTPSenderRefused as e:
    print('Failed to send the email. Sender was rejected:', e.smtp_code, e.smtp_error)
except smtplib.SMTPRecipientsRefused as e:
    print('Failed to send the email. Recipients were rejected:', e.smtp_code, e.smtp_error)
except smtplib.SMTPDataError as e:
    print('Failed to send the email. Data was rejected:', e.smtp_code, e.smtp_error)
except smtplib.SMTPException as e:
    print('Failed to send the email, ', str(e))
except Exception as e:
    print('An exception occurred while sending the email, ', str(e))