当前位置: 首页 > article >正文

通过阿里云服务发送邮件

通过阿里云服务发送邮件

  • 1. 整体描述
  • 2. 方案选择
    • 2.1 控制台发送
    • 2.2 API接口接入
    • 2.3 SMTP接口接入
    • 2.4 结论
  • 3. 前期工作
    • 3.1 准备工作
    • 3.2 配置工作
    • 3.3 总结
  • 4. 收费模式
    • 4.1 免费额度
    • 4.2 资源包
    • 4.3 按量付费
  • 5. Demo开发
    • 5.1 选择SMTP服务器
    • 5.2 pom引用
    • 5.3 demo代码
    • 5.4 运行结果
  • 6 总结

1. 整体描述

项目有发送邮件的需求,主要就对阿里云服务器发送邮件的功能调研了一下

2. 方案选择

阿里云提供三种发送邮件的方式,分别为: 控制台发送,API接口发送和SMTP方式发送。

2.1 控制台发送

无需开发,在控制台配置发送,目前支持发送批量邮件,暂不支持触发邮件。

2.2 API接口接入

编写程序,调用邮件推送产品的 API 接口,传输邮件数据。请求成功后,邮件推送对邮件数据进行处理和投递。通过接口可以发送触发邮件和批量邮件。不支持添加附件。

2.3 SMTP接口接入

编写程序,调用标准的 SMTP 接口,传输邮件数据。通过 SMTP 接口可以发送触发邮件和批量邮件。
优点:标准化的邮件发送协议,轻松接入无需额外的接口适配。

2.4 结论

暂定使用SMTP方式,阿里云官方建议使用此方式,开发相对简单。

3. 前期工作

3.1 准备工作

  1. 申请阿里云账号,在控制台中搜索【邮箱推送】控制台,开通并配置邮箱服务。
  2. 申请域名,最好在阿里云上申请,此域名为发送邮件的域名地址。域名申请会有一定费用,具体和域名有关,.com的域名收费较高。在阿里云搜索【域名】控制台,可以购买域名。

3.2 配置工作

  1. 在阿里云【邮件推送】控制台,增加发信域名,填写上面申请的域名
    域名设置
  2. 登录域名注册商网站,将查询的域名配置记录值逐条添加域名解析,使用阿里云网站,直接可以在阿里云【云解析DNS】的控制台直接设置。
    域名配置
  3. 等待控制台域名状态验证通过,一般一两个小时完成验证,如果状态还是验证中,可以手动点击执行验证操作。
    域名配置
  4. 在阿里云【邮件推送】控制台,增加发信地址,并设置SMTP密码
    设置地址
  5. 【可选】在阿里云【邮件推送】控制台,设置标签。标签可以便于阿里云控制台统计。

3.3 总结

完成以上配置,即可进入Demo开发和测试阶段。

4. 收费模式

阿里云官方文档:阿里云发送邮件文档

4.1 免费额度

邮件推送的每个阿里云主账户,享有共2000封免费发信额度,每天最多免费发送200封。
如用户有免费发信额度,免费额度将不包含在资源包或按量计费范围内,超过免费额度的邮件量会产生费用。

4.2 资源包

资源包是预付费方式。资源包购买成功后,立即生效。
购买时长(即有效期):6 个月。每个资源包的有效期独立计算,多个资源包有效期不会叠加。
扣减方式:购买的资源包在有效期内,优先扣减资源包内的邮件量。多个资源包按有效期先结束的优先扣减,当所有资源包扣减完毕后,自动转为按量计费的方式扣减。
资源包使用后或资源包到期后,剩余流量不支持退订、不支持退款。

4.3 按量付费

按量付费是后付费方式,按照实际使用量计费,单价为 2 元/1000 封。该计费方式无须主动开通,邮件推送产品开通后,默认为按量付费。如果您购买了资源包,当资源包内的额度使用完之后,自动转按量付费。
计算公式为: 按量计费的费用 = 邮件发送量 / 1000 X 2.00 元。
费用精确到小数点后 2 位,即最低账单金额为 0.01 元。

5. Demo开发

5.1 选择SMTP服务器

不同站点的SMTP服务地址:
华东 1(杭州): smtpdm.aliyun.com
新加坡(新):smtpdm-ap-southeast-1.aliyuncs.com
美国(新):smtpdm-us-east-1.aliyuncs.com
德国:smtpdm-eu-central-1.aliyuncs.com
SMTP端口号:25,80,465(SSL加密)
注意:ECS 基于安全考虑,目前已禁用 25 端口。
请根据控制台选择的服务区域选择对应的服务器地址。
综上,Demo选择华东 1(杭州): smtpdm.aliyun.com,端口号使用80。

5.2 pom引用

		<dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.6</version></dependency>

5.3 demo代码

package org.example;import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
import java.util.UUID;public class SampleMail {// 配置常量private static final String SMTP_HOST = "smtpdm.aliyun.com";private static final int SMTP_PORT = 80;private static final String USER_NAME = "之前注册的邮件域名";private static final String PASSWORD = "邮件密码,在阿里云设置的";protected static String genMessageID(String mailFrom) {// 生成Message-ID:if (!mailFrom.contains("@")) {throw new IllegalArgumentException("Invalid email format: " + mailFrom);}String domain = mailFrom.split("@")[1];UUID uuid = UUID.randomUUID();return "<" + uuid.toString() + "@" + domain + ">";}private static void setRecipients(MimeMessage message, Message.RecipientType type, String[] recipients) throws MessagingException {// 设置收件人地址if (recipients == null || recipients.length == 0) {return; // 空列表不设置}InternetAddress[] addresses = new InternetAddress[recipients.length];for (int h = 0; h < recipients.length; h++) {addresses[h] = new InternetAddress(recipients[h]);}message.setRecipients(type, addresses);}public static void main(String[] args) throws MessagingException, UnsupportedEncodingException {// 配置发送邮件的环境属性final Properties props = new Properties();// 表示SMTP发送邮件,需要进行身份验证props.put("mail.smtp.auth", "true");props.put("mail.smtp.host", SMTP_HOST);//设置端口:props.put("mail.smtp.port", SMTP_PORT);//或"25", 如果使用ssl,则去掉使用80或25端口的配置,进行如下配置://加密方式://props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");//props.put("mail.smtp.socketFactory.fallback", "false");//禁止回退非加密//props.put("mail.smtp.socketFactory.port", "465");//props.put("mail.smtp.port", "465");props.put("mail.smtp.from", USER_NAME);    //mailfrom 参数props.put("mail.user", USER_NAME);// 发件人的账号(在控制台创建的发信地址)props.put("mail.password", PASSWORD);// 发信地址的smtp密码(在控制台选择发信地址进行设置)//props.put("mail.smtp.connectiontimeout", 1000);System.setProperty("mail.mime.splitlongparameters", "false");//用于解决附件名过长导致的显示异常//props.setProperty("mail.smtp.ssl.enable", "true");  //请配合465端口使用// 构建授权信息,用于进行SMTP进行身份验证Authenticator authenticator = new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(USER_NAME, PASSWORD);}};//使用环境属性和授权信息,创建邮件会话Session mailSession = Session.getInstance(props, authenticator);String messageIDValue = genMessageID(USER_NAME);MimeMessage message = new MimeMessage(mailSession) {@Overrideprotected void updateMessageID() throws MessagingException {setHeader("Message-ID", messageIDValue);}};try {// 设置发件人邮件地址和名称。填写控制台配置的发信地址。和上面的mail.user保持一致。名称用户可以自定义填写。InternetAddress from = new InternetAddress(USER_NAME, "发件人昵称");//from 参数,可实现代发,注意:代发容易被收信方拒信或进入垃圾箱。message.setFrom(from);setRecipients(message, Message.RecipientType.TO, new String[]{"接收邮件地址"});InternetAddress replyToAddress = new InternetAddress("回信地址");message.setReplyTo(new Address[]{replyToAddress});//可选。设置回信地址message.setSentDate(new Date());message.setSubject("测试主题");//发送附件和内容:// 创建多重消息Multipart multipart = new MimeMultipart();// 创建一个BodyPart用于HTML内容BodyPart htmlPart = new MimeBodyPart();htmlPart.setContent("测试<br> html内容4", "text/html;charset=UTF-8");//设置邮件的内容,会覆盖前面的message.setContentmultipart.addBodyPart(htmlPart);//附件部分//发送附件,总的邮件大小不超过15M,创建消息部分。// 发送本地附件String[] fileList = {"C:\\Users\\18708\\Desktop\\test.txt"};for (String filePath : fileList) {MimeBodyPart mimeBodyPart = new MimeBodyPart();FileDataSource fileDataSource = new FileDataSource(filePath);mimeBodyPart.setDataHandler(new DataHandler(fileDataSource));//处理附件名称中文(附带文件路径)乱码问题mimeBodyPart.setFileName(MimeUtility.encodeWord(fileDataSource.getName()));mimeBodyPart.addHeader("Content-Transfer-Encoding", "base64");multipart.addBodyPart(mimeBodyPart);}// 添加完整消息message.setContent(multipart);// 发送附件代码,结束mailSession.setDebug(true);//开启debug模式Transport.send(message);System.out.println("发送完成!");} catch (MessagingException | UnsupportedEncodingException e) {System.err.println("邮件发送失败: " + e.getMessage());e.printStackTrace();}}}

5.4 运行结果

正常运行之后,会log出发送完成,几秒钟之后会收到邮件,但是这里有个问题是,不管代码里写的收件箱是否是真实有效的,在log里也都是发送完成。也就是说,在发送的代码里,无法知道邮件是否真正投递到对方邮箱中。

6 总结

至此,发送邮件DEMO功能基本完成,不过只是个demo,要想在项目中使用,还需要考虑很多其他的问题,还要封装一层接口,目前的几个问题:垃圾邮件,使用QQ邮箱作为收件箱,有可能会进入到垃圾箱中,阿里云建议在收件方设置,将发送邮件的域名标记为白名单。发送记录:发送记录接口目前没找到(应该是没有),此接口程序可以自己实现,不需要使用阿里云接口。发送失败策略:初步思路:建立发送失败表,每隔一段时间查询失败的数据重新发送,成功之后清除。

相关文章:

通过阿里云服务发送邮件

通过阿里云服务发送邮件 1. 整体描述2. 方案选择2.1 控制台发送2.2 API接口接入2.3 SMTP接口接入2.4 结论 3. 前期工作3.1 准备工作3.2 配置工作3.3 总结 4. 收费模式4.1 免费额度4.2 资源包4.3 按量付费 5. Demo开发5.1 选择SMTP服务器5.2 pom引用5.3 demo代码5.4 运行结果 6 …...

Vad-R1:通过从感知到认知的思维链进行视频异常推理

文章目录 速览摘要1 引言2 相关工作视频异常检测与数据集视频多模态大语言模型具备推理能力的多模态大语言模型 3 方法&#xff1a;Vad-R13.1 从感知到认知的思维链&#xff08;Perception-to-Cognition Chain-of-Thought&#xff09;3.2 数据集&#xff1a;Vad-Reasoning3.3 A…...

黑马Java面试笔记之MySQL篇(事务)

一. 事务的特性 事务的特性是什么&#xff1f;可以详细说一下吗&#xff1f; 事务是一组操作的集合&#xff0c;他是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失…...

群辉(synology)NAS老机器连接出现网页端可以进入,但是本地访问输入一样的账号密码是出现错误时解决方案

群辉&#xff08;synology&#xff09;NAS老机器连接出现网页端可以进入&#xff0c;但是本地访问输入一样的账号密码是出现错误时解决方案 老机器 装的win7 系统 登入后端网页端的时候正常&#xff0c;但是本地访问登入时输入登入网页端一样的密码时候出现问题解决方案 1.登…...

C++多重继承详解与实战解析

#include <iostream> using namespace std; //基类&#xff0c;父类 class ClassA { public:void displayA() {std::cout << "Displaying ClassA" << std::endl;}void testFunc(){std::cout << "testFunc ClassA" << std::e…...

【深度学习】实验四 卷积神经网络CNN

实验四 卷积神经网络CNN 一、实验学时&#xff1a; 2学时 二、实验目的 掌握卷积神经网络CNN的基本结构&#xff1b;掌握数据预处理、模型构建、训练与调参&#xff1b;探索CNN在MNIST数据集中的性能表现&#xff1b; 三、实验内容 实现深度神经网络CNN。 四、主要实验步…...

实现一个免费可用的文生图的MCP Server

概述 文生图模型为使用 Cloudflare Worker AI 部署 Flux 模型&#xff0c;是参照视频https://www.bilibili.com/video/BV1UbkcYcE24/?spm_id_from333.337.search-card.all.click&vd_source9ca2da6b1848bc903db417c336f9cb6b的复现Cursor MCP Server实现是参照文章https:/…...

无公网ip远程桌面连接不了怎么办?内网计算机让外网访问方法和问题分析

无公网IP时&#xff0c;可以通过内网穿透技术实现远程桌面连接‌。 具体方法包括使用 NAT123 或类似端口映射软件将内网IP和端口映射到公网域名和端口上。用户需要在本地安装NAT123客户端&#xff0c;并登录添加设置映射&#xff0c;将内网的远程桌面连接IP和3389端口映射到一…...

【手搓一个原生全局loading组件解决页面闪烁问题】

页面闪烁效果1 页面闪烁效果2 封装一个全局loading组件 class GlobalLoading extends HTMLElement {constructor() {super();this.attachShadow({ mode: open });}connectedCallback() {this.render();this.init();}render() {this.shadowRoot.innerHTML <style>.load…...

CSS基础巩固-基础-选择

目录 CSS是如何工作的&#xff1f; 当浏览器遇到无法解析的CSS代码时 如何导入CSS样式&#xff1f; 改变元素的默认样式 选择 前缀符号&#xff08;后面会具体介绍&#xff09; 优先级 同时应用样式到多个类上 属性选择器 伪类 伪元素 关系选择器 后代选择器 子代…...

一种在SQL Server中传递多行数据的方法

这是一种比较偷懒的方法&#xff0c;其实各种数据库对Json 支持的很好。sql server 、oracle都不错。所以可以直接传json declare 这是一个json varchar(max) set 这是一个json{"data":[{"code":"1","name":"啥1"},{"…...

【Docker 从入门到实战全攻略(一):核心概念 + 命令详解 + 部署案例】

1. 是什么 Docker 是一个用于开发、部署和运行应用程序的开源平台&#xff0c;它使用 容器化技术 将应用及其依赖打包成独立的容器&#xff0c;确保应用在不同环境中一致运行。 2. Docker与虚拟机 2.1 Docker&#xff08;容器化&#xff09; 容器化是一种轻量级的虚拟化技术…...

github 提交失败,连接不上

1. 第一种情况&#xff0c;开了加速器&#xff0c;导致代理错误 删除hosts文件里相关的github代理地址 2. 有些ip不支持22端口连接,改为443连接 ssh -vT gitgithub.com // 命令执行结果 OpenSSH_for_Windows_9.5p1, LibreSSL 3.8.2 debug1: C…...

系统架构设计师(一):计算机系统基础知识

系统架构设计师&#xff08;一&#xff09;&#xff1a;计算机系统基础知识 引言计算机系统概述计算机硬件处理器处理器指令集常见处理器 存储器总线总线性能指标总线分类按照总线在计算机中所处的位置划分按照连接方式分类按照功能分类 接口接口分类 计算机软件文件系统文件类…...

VMware安装Ubuntu全攻略

VMware安装Ubuntu实战分享大纲 准备工作 列出安装前的必要条件和工具,包括硬件要求、软件下载链接等。 VMware Workstation Pro/Player的安装与激活Ubuntu镜像文件下载(官方推荐版本)确保主机系统满足虚拟化技术(VT-x/AMD-V)要求创建虚拟机 详细描述在VMware中创建新虚…...

清理 pycharm 无效解释器

1. 起因&#xff0c; 目的: 经常使用 pycharm 来调试深度学习项目&#xff0c;每次新建虚拟环境&#xff0c;都是显示一堆不存在的名称&#xff0c;删也删不掉。 总觉得很烦&#xff0c;是个痛点。决定深入研究一下。 2. 先看效果 效果是能行&#xff0c;而且清爽多了。 3. …...

精益数据分析(92/126):指标基准化——如何判断你的数据表现是否足够优秀

精益数据分析&#xff08;92/126&#xff09;&#xff1a;指标基准化——如何判断你的数据表现是否足够优秀 在创业过程中&#xff0c;面对纷繁复杂的指标数据&#xff0c;创业者常常困惑于“什么样的表现算优秀”“我的数据是否达标”。今天&#xff0c;我们将通过WP Engine的…...

手机如何压缩文件为 RAR 格式:详细教程与工具推荐

在如今这个数字化时代&#xff0c;手机已经成为我们生活中不可或缺的工具。随着我们使用手机的频率越来越高&#xff0c;手机中的文件也越来越多&#xff0c;照片、视频、文档等各种类型的文件不断占据着手机的存储空间。 据统计&#xff0c;普通用户的手机存储空间中&#xf…...

Elasticsearch集群管理的相关工具介绍

Elasticsearch 集群管理涉及节点监控、配置管理、故障排查、性能优化等多个环节,依赖一系列官方工具和社区方案实现高效运维。以下从 官方工具链、生态集成工具、社区辅助工具 三个维度介绍核心工具及其应用场景: 一、官方核心工具链 1. Elasticsearch 内置功能 _cluster 接…...

基于多尺度卷积和扩张卷积-LSTM的多变量时间序列预测

时间序列预测是机器学习和数据分析中的重要领域,广泛应用于金融、气象、交通等领域。本文将介绍一种结合多尺度卷积、扩张卷积和LSTM的混合神经网络模型,用于多变量时间序列预测,并提供完整的代码实现和详细讲解。 1. 模型架构概述 我们提出的模型结合了三种强大的神经网络…...

Java 注解式限流教程(使用 Redis + AOP)

Java 注解式限流教程&#xff08;使用 Redis AOP&#xff09; 在上一节中&#xff0c;我们已经实现了基于 Redis 的请求频率控制。现在我们将进一步升级功能&#xff0c;使用 Spring AOP 自定义注解 实现一个更优雅、可复用的限流方式 —— 即通过 RateLimiter 注解&#xf…...

C# XAML 基础:构建现代 Windows 应用程序的 UI 语言

在现代 Windows 应用程序开发中&#xff0c;XAML (eXtensible Application Markup Language) 扮演着至关重要的角色。作为一种基于 XML 的声明性语言&#xff0c;XAML 为 WPF (Windows Presentation Foundation)、UWP (Universal Windows Platform) 和 Xamarin.Forms 应用程序提…...

Linux运维笔记:服务器感染 netools 病毒案例

文章目录 背景排查过程1. 发现异常2. 检测隐藏进程3. 尝试终止进程4. 深入分析进程 处理步骤1. 禁用 Cron 任务2. 删除恶意文件3. 终止恶意进程4. 重启系统 注意事项总结 提示&#xff1a;本文记录了一起 Linux 服务器感染恶意软件&#xff08;疑似挖矿病毒&#xff09;的排查与…...

(面试)获取View宽高的几种方式

Android 中获取 View 宽高的几种方式&#xff0c;以及它们的适用场景和注意事项&#xff1a; 1. View.getWidth() 和 View.getHeight() 原理: 直接从 View 对象中获取已经计算好的宽度和高度。 优点: 简单直接。 缺点: 在 onCreate()、onStart() 等生命周期方法中&#xff0…...

【Linux】进程地址空间揭秘(初步认识)

10.进程地址空间&#xff08;初步认识&#xff09; 文章目录 10.进程地址空间&#xff08;初步认识&#xff09;一、进程地址空间的实验现象解析二、进程地址空间三、虚拟内存管理补充&#xff1a;数据的写时拷贝&#xff08;浅谈&#xff09;补充&#xff1a;页表&#xff08;…...

设计模式——备忘录设计模式(行为型)

摘要 备忘录设计模式是一种行为型设计模式&#xff0c;用于在不破坏封装性的前提下&#xff0c;捕获对象的内部状态并在需要时恢复。它包含三个关键角色&#xff1a;原发器&#xff08;Originator&#xff09;、备忘录&#xff08;Memento&#xff09;和负责人&#xff08;Car…...

吴恩达:构建自动化评估并不需要大量投入,从一些简单快速的示例入手,然后逐步迭代!

吴恩达老师又来信了。 这次他分享了一个重要观点&#xff1a;构建自动化评估并不需要大量投入。从一些简单快速的示例入手&#xff0c;然后逐步迭代&#xff01; 以下是我对原文的翻译&#xff1a; 亲爱的朋友们&#xff1a; 我注意到&#xff0c;许多生成式 AI 应用项目在系…...

鸿蒙OSUniApp内存管理优化实战:从入门到精通#三方框架 #Uniapp

UniApp内存管理优化实战&#xff1a;从入门到精通 在开发 UniApp 应用时&#xff0c;特别是针对鸿蒙设备的开发过程中&#xff0c;内存管理往往成为影响应用性能的关键因素。本文将结合实际项目经验&#xff0c;深入探讨 UniApp 应用的内存优化策略&#xff0c;帮助开发者构建…...

Vue-5-基于JavaScript和plotly.js绘制数据分析类图表

文章目录 1 折线图示例1.1 网页基本结构1.2 绘图流程1.2.1 type图表类型1.2.2 mode显示方式1.2.3 marker数据点的样式1.3 横坐标为时间戳1.3.1 xaxis.type坐标值类型1.3.2 xaxis.tickformat格式1.4 悬停时展示毫秒数2 一个变量2.1 箱线图2.2 小提琴图2.3 直方图3 两个变量3.1 折…...

UI自动化测试的革新,新一代AI工具MidScene.js实测!

前言 AI已经越来越深入地走入我们的实际工作,在软件测试领域,和AI相关的新测试工具、方法也层出不穷。在之前我们介绍过结合 mcp server 实现 AI 驱动测试的案例,本文我们将介绍一个近期崭露头角的国产AI测试工具 Midscene.js Midscene.js简介 MidScene.js 是由字节跳动 w…...