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:
Construir un mensaje
MIMEMultipartcon los encabezados To, Cc, Bcc, Reply-To y Return-Path.Adjuntar un cuerpo HTML (el texto sin formato y los archivos adjuntos están disponibles como opciones comentadas).
Conectarse a
smtpdm.aliyun.comen el puerto 80 (o en el puerto 465 para SSL) y autenticarse con la dirección del remitente y la contraseña SMTP.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 |
|
|
Dirección de remitente creada en la consola de Direct Mail. Se usa como inicio de sesión SMTP y como argumento FROM de |
|
|
Contraseña SMTP correspondiente a la dirección del remitente. No es la contraseña de su cuenta de Alibaba Cloud. |
|
|
Dirección que recibe las respuestas. Es independiente de la dirección del remitente, ya que esta última no recibe respuestas. |
|
|
Listas de destinatarios para To, Cc y Bcc. La suma total de las tres listas no puede exceder 60 direcciones por envío. |
|
|
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/plainjunto 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.SMTPporsmtplib.SMTP_SSLen el puerto 465. Si el protocolo de enlace SSL falla en Python 3.10 o 3.11, cree un contexto SSL personalizado conctxt.set_ciphers('DEFAULT').Seguimiento de correo electrónico: Configure el encabezado
X-AliDM-Tracecon 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).