如何在Azure Data Factory中发送含文件列表的邮件通知
实现方案:Azure Data Factory结合Databricks/AKS发送文件清单邮件
方案一:使用Databricks(推荐)
实现流程
- 在ADF完成文件传输至FileShare的任务后,添加Databricks Notebook活动,确保该活动依赖于文件传输任务(即传输完成后触发)
- 在Databricks Notebook中完成两项核心操作:
- 连接Azure File Share,拉取已传输的文件列表
- 通过无凭据SMTP服务器发送包含文件清单的邮件
- 提前配置Databricks集群权限,确保其能访问目标存储账户
伪代码(Databricks Notebook,Python)
首先挂载Azure File Share(可配置为集群初始化脚本,避免重复执行):
# 挂载Azure File Share dbutils.fs.mount( source = "wasbs://<容器名>@<存储账户名>.blob.core.windows.net/", mount_point = "/mnt/fileshare", extra_configs = {"fs.azure.account.key.<存储账户名>.blob.core.windows.net": "<存储账户访问密钥>"} )
获取文件列表并发送邮件:
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart # 1. 提取FileShare中的文件列表(排除文件夹) file_list = dbutils.fs.ls("/mnt/fileshare") file_names = [file.name for file in file_list if not file.isDir()] # 2. 构造邮件内容 sender = "sender@yourdomain.com" receivers = ["user1@yourdomain.com", "user2@yourdomain.com"] subject = "FileShare已传输文件清单" # 同时准备纯文本和HTML格式内容 plain_body = "已成功传输的文件如下:\n\n" + "\n".join(file_names) html_body = f""" <p>已成功传输至FileShare的文件清单:</p> <ul> {"".join([f"<li>{name}</li>" for name in file_names])} </ul> """ # 组装多格式邮件 msg = MIMEMultipart("alternative") msg["From"] = sender msg["To"] = ", ".join(receivers) msg["Subject"] = subject msg.attach(MIMEText(plain_body, "plain")) msg.attach(MIMEText(html_body, "html")) # 3. 连接SMTP服务器发送邮件 smtp_host = "your-smtp-server.com" smtp_port = 25 # 或对应无加密/明文端口 try: with smtplib.SMTP(smtp_host, smtp_port) as server: # 无需认证,直接发送 server.sendmail(sender, receivers, msg.as_string()) print("邮件发送成功") except Exception as e: print(f"邮件发送失败:{str(e)}") raise e
方案二:使用AKS
实现流程
- 在AKS中部署一个轻量Web服务(如Python Flask),封装文件列表获取和邮件发送逻辑
- 在ADF中添加Web活动,设置依赖于文件传输任务,通过POST请求触发AKS服务的邮件发送接口
- 确保AKS集群能访问Azure File Share和目标SMTP服务器
伪代码(AKS部署的Python Flask服务)
服务核心代码:
from flask import Flask, request, jsonify import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from azure.storage.fileshare import ShareFileClient app = Flask(__name__) # 配置参数 STORAGE_ACCOUNT = "your-storage-account" STORAGE_KEY = "your-storage-key" FILE_SHARE = "your-file-share" SMTP_SERVER = "your-smtp-server.com" SMTP_PORT = 25 @app.route('/send-email', methods=['POST']) def send_email(): # 1. 从请求体获取发件人、收件人信息 req_data = request.get_json() sender = req_data.get('sender') receivers = req_data.get('receivers') # 2. 获取FileShare文件列表 share_client = ShareFileClient( account_url=f"https://{STORAGE_ACCOUNT}.file.core.windows.net", share_name=FILE_SHARE, credential=STORAGE_KEY ) file_names = [] for item in share_client.list_directories_and_files(): if not item['is_directory']: file_names.append(item['name']) # 3. 构造并发送邮件 subject = "FileShare已传输文件清单" plain_body = "已成功传输的文件如下:\n\n" + "\n".join(file_names) html_body = f""" <p>已成功传输至FileShare的文件清单:</p> <ul> {"".join([f"<li>{name}</li>" for name in file_names])} </ul> """ msg = MIMEMultipart("alternative") msg["From"] = sender msg["To"] = ", ".join(receivers) msg["Subject"] = subject msg.attach(MIMEText(plain_body, "plain")) msg.attach(MIMEText(html_body, "html")) try: with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server: server.sendmail(sender, receivers, msg.as_string()) return jsonify({"status": "success", "message": "邮件发送成功"}) except Exception as e: return jsonify({"status": "failed", "message": f"邮件发送失败:{str(e)}"}), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
ADF Web活动配置:
- 请求方法:POST
- URL:AKS服务的外部访问地址(如
http://<aks-service-ip>:5000/send-email) - 请求体:
{ "sender": "sender@yourdomain.com", "receivers": ["user1@yourdomain.com", "user2@yourdomain.com"] }
注意事项
- 若SMTP服务器支持TLS加密,需在代码中添加
server.starttls()步骤(无凭据仍可使用) - 确保Databricks/AKS的出站IP在SMTP服务器的防火墙白名单内
- Databricks挂载FileShare时,可使用服务主体替代存储密钥提升安全性
内容的提问来源于stack exchange,提问作者TalendDeveloper
相关产品推荐
相关产品推荐

