Todos los productos
Search
Centro de documentos

Direct Mail:Ejemplo de llamada SMTP para Python 3.6 o posterior

Última actualización: Sep 03, 2026

Envíe correos electrónicos desde Python 3.6 o posterior mediante el endpoint SMTP de Direct Mail.

Requisitos previos

Antes de empezar, asegúrese de contar con lo siguiente:

  • Una dirección de remitente creada en la consola de Direct Mail

  • Una contraseña SMTP generada para dicha dirección de remitente

  • Python 3.6 o posterior instalado

Advertencia: No escriba su contraseña SMTP directamente en el código fuente. Almacene las credenciales en variables de entorno o en un administrador de secretos y léalas durante la ejecución.

Funcionamiento

El ejemplo usa las bibliotecas integradas de Python smtplib y email para:

  1. Construir un mensaje MIMEMultipart con los encabezados To, Cc, Bcc, Reply-To y Return-Path.

  2. Adjuntar un cuerpo HTML (el texto sin formato y los archivos adjuntos están disponibles como opciones comentadas).

  3. Conectarse a smtpdm.aliyun.com en el puerto 80 (o en el puerto 465 para SSL) y autenticarse con la dirección del remitente y la contraseña SMTP.

  4. Enviar el mensaje a todos los destinatarios en una sola llamada y gestionar los errores SMTP según su tipo.

Código de ejemplo

# -*- 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 sender address created in the Direct Mail console.
username = 'XXXXXXXX'
# The SMTP password for the sender address.
password = 'XXXXXXXX'
# The reply-to address. When a recipient replies, the email goes to this address
# instead of the sender address, which does not receive replies.
replyto = 'XXXXXXXX'
# The To recipient addresses (displayed in the email header).
rcptto = ['address1@example.net', 'address2@example.net']
# The Cc recipient addresses (displayed in the email header).
rcptcc = ['address3@example.net', 'address4@example.net']
# The Bcc recipient addresses (hidden from recipients but receive the email).
rcptbcc = ['address5@example.net', 'address6@example.net']
# All recipients. A single send cannot exceed 60 addresses.
receivers = rcptto + rcptcc + rcptbcc

# Build the message.
msg = MIMEMultipart('alternative')
msg['Subject'] = Header('Custom email subject')
msg['From'] = formataddr(["Custom sender nickname", username])  # Nickname + sender address (or proxy sender)
msg['To'] = ",".join(rcptto)
msg['Cc'] = ",".join(rcptcc)
msg['Reply-to'] = replyto  # Address that receives replies. The recipient must support standard protocols.
msg['Return-Path'] = 'test@example.net'  # Address that receives bounces. The recipient must support standard protocols.
msg['Message-id'] = email.utils.make_msgid()  # Unique identifier per RFC 5322, e.g. <uniquestring@example.com>.
msg['Date'] = email.utils.formatdate()

# To enable email tracking, uncomment the following section.
# A tag is required and must be created in the console at least 10 minutes before use.
# tagName = 'xxxxxxx'
#
# trace = {
#     "OpenTrace": '1',  # Enable open tracking.
#     "LinkTrace": '1',  # Enable link-click tracking.
#     "TagName": tagName
# }
# jsonTrace = json.dumps(trace)
# base64Trace = str(base64.b64encode(jsonTrace.encode('utf-8')), 'utf-8')
# msg.add_header("X-AliDM-Trace", base64Trace)

# To add a plain-text fallback for mail clients that do not render HTML, uncomment the following.
# textplain = MIMEText('Custom plain text part', _subtype='plain', _charset='UTF-8')
# msg.attach(textplain)

# HTML body.
texthtml = MIMEText('Custom HTML hypertext part', _subtype='html', _charset='UTF-8')
msg.attach(texthtml)

# To attach a local file, uncomment the following.
# 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())
#     part_attach1.add_header('Content-Disposition', 'attachment', filename=filename)
#     msg.attach(part_attach1)

# To attach a file from a URL (e.g., an OSS object), uncomment the following.
# 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())
#     part_attach1.add_header('Content-Disposition', 'attachment', filename=filename)
#     msg.attach(part_attach1)

# Send the email.
try:
    # To use SSL, replace the line below with:
    # client = smtplib.SMTP_SSL('smtpdm.aliyun.com', 465)
    #
    # If the SSL handshake fails on Python 3.10 or 3.11, use a custom context:
    # ctxt = ssl.create_default_context()
    # ctxt.set_ciphers('DEFAULT')
    # client = smtplib.SMTP_SSL('smtpdm.aliyun.com', 465, context=ctxt)

    # Standard SMTP on port 80 (port 25 is also supported).
    client = smtplib.SMTP('smtpdm.aliyun.com', 80)
    client.set_debuglevel(0)  # Set to 1 to enable debug output.
    # The sender address and authentication address must match.
    client.login(username, password)
    client.sendmail(username, receivers, msg.as_string())
    client.quit()
    print('Email sent successfully!')
except smtplib.SMTPConnectError as e:
    print('Failed to send email. Connection failed:', e.smtp_code, e.smtp_error)
except smtplib.SMTPAuthenticationError as e:
    print('Failed to send email. Authentication error:', e.smtp_code, e.smtp_error)
except smtplib.SMTPSenderRefused as e:
    print('Failed to send email. Sender refused:', e.smtp_code, e.smtp_error)
except smtplib.SMTPRecipientsRefused as e:
    print('Failed to send email. Recipients refused:', e.smtp_code, e.smtp_error)
except smtplib.SMTPDataError as e:
    print('Failed to send email. Data reception refused:', e.smtp_code, e.smtp_error)
except smtplib.SMTPException as e:
    print('Failed to send email:', str(e))
except Exception as e:
    print('Exception while sending email:', str(e))

Parámetros clave

Parámetro

Descripción

username

Dirección de remitente creada en la consola de Direct Mail. Se usa como inicio de sesión SMTP y como argumento FROM de sendmail; los tres valores deben coincidir.

password

Contraseña SMTP correspondiente a la dirección del remitente. No es la contraseña de su cuenta de Alibaba Cloud.

replyto

Dirección que recibe las respuestas. Es independiente de la dirección del remitente, ya que esta última no recibe respuestas.

rcptto / rcptcc / rcptbcc

Listas de destinatarios para To, Cc y Bcc. La suma total de las tres listas no puede exceder 60 direcciones por envío.

smtpdm.aliyun.com

Endpoint SMTP de Direct Mail. Use el puerto 80 o 25 para SMTP estándar, o el puerto 465 para SSL.

Funciones opcionales

El ejemplo incluye código comentado para las siguientes funciones. Descomente las secciones correspondientes para habilitarlas.

  • Cuerpo de texto sin formato: Agregue una parte alternativa text/plain junto al cuerpo HTML. Los clientes de correo que no procesan HTML usarán la versión de texto sin formato.

  • Archivo adjunto local: Lea un archivo del disco y adjúntelo mediante MIMEApplication.

  • Archivo adjunto desde URL: Obtenga un archivo desde una URL (por ejemplo, un objeto de OSS) y adjúntelo sin guardarlo previamente en el disco.

  • Conexión SSL: Reemplace smtplib.SMTP por smtplib.SMTP_SSL en el puerto 465. Si el protocolo de enlace SSL falla en Python 3.10 o 3.11, cree un contexto SSL personalizado con ctxt.set_ciphers('DEFAULT').

  • Seguimiento de correo electrónico: Configure el encabezado X-AliDM-Trace con una carga útil JSON codificada en Base64 para habilitar el seguimiento de apertura y de clics en enlaces. Requiere una etiqueta creada en la consola de Direct Mail (disponible 10 minutos después de su creación).