SMTP简单邮件传输协议(C/C++ 发送电子邮件)

news2024/11/26 14:39:49

SMTP是用于通过Internet发送电子邮件的协议。电子邮件客户端(如Microsoft Outlook或macOS Mail应用程序)使用SMTP连接到邮件服务器并发送电子邮件。邮件服务器还使用SMTP将邮件从一个邮件服务器交换到另一个。它不用于从服务器下载电子邮件;相反,IMAP和POP3协议检索邮件。

SMTP客户端首先通过TCP与邮件服务器建立连接。然后,客户端将消息推送到服务器,服务器会检查收件人的电子邮件地址,看看他们是否与发件人在同一个域上;如果他们是,它可以传递信息。否则,它会运行DNS查询来查找收件人邮件服务器的IP地址。然后,邮件服务器与目标邮件服务器建立另一个SMTP连接以发送邮件。

SMTP的基本命令

正如我们前面提到的,SMTP命令是一组代码,为服务器之间的电子邮件传输提供动力。以下是您应该注意的基本SMTP命令:

HELO或EHLO(你好):这是开始整个电子邮件发送过程的关键命令。电子邮件客户端正在向SMTP服务器标识自己。这是一个对话的开始,通常涉及服务器发回一个HELO命令及其域名/IP地址。

MAIL FROM:根据标识命令,发件人将共享指定邮件发件人的代码。这会列出电子邮件地址,并告诉SMTP服务器新事务即将开始。从这里开始,服务器重置所有内容,并准备接受电子邮件地址。一旦被接受,它将回复一个250 OK的回复代码。

RCPT TO(Recipient TO):下一个命令位于250 OK回复代码之后,该代码用于识别电子邮件的发送对象。同样,SMTP服务器使用相同的代码进行响应,此时可以使用不同收件人的电子邮件地址发送另一个RCPT TO命令。这可以根据需要来回多次,具体取决于收到电子邮件的人数。

DATA 数据:这会触发客户端和服务器之间的数据传输。所有邮件内容都将移动到SMTP服务器,SMTP服务器将以345回复代码进行响应。消息的内容被传输到服务器,在服务器中,一个点被单独发送到一行中,以表示消息的结束。如果接受并准备好交付,服务器将发送另一个250 OK代码。此时,邮件正在发送给收件人的途中。

QUIT:发送电子邮件后,客户端向服务器发送QUIT命令,切断连接。如果已成功关闭,服务器将回复221代码。

RSET(Reset):当邮件事务需要中止时,会将此命令发送到服务器。它不会关闭连接,但会重置所有内容,并删除有关电子邮件和相关方的所有以前的数据。当出现错误时,通常会使用此方法,例如输入错误的收件人信息,并且需要重新启动流程。

将这些命令想象成允许电子邮件服务器之间进行对话的语言。他们的聊天看起来有点像这样:


还有其他SMTP命令可以处理身份验证并增强安全性,例如AUTH和STARTTLS。如果您有兴趣了解它们或查看SMTP在工作中的示例,请阅读本SMTP命令指南。

Linux使用mail配合smtp发送邮件

邮件安装工具:

yum -y install mailx
yum -y install sendmail

开启与关闭邮件服务:

systemctl enable sendmail
systemctl stop sendmail

开启邮箱imap/smtp服务

我这里使用的是163的邮箱,步骤如下:
登录邮箱后,点击页面顶部的“设置”菜单,在下拉框中点击“POP3/SMTP/IMAP”项

由于我这里已经开启过,就不再演示了。初始勾选后会让你填写手机号码,发送验证码,成功填写后,会让你输入授权码,这个是作为smtp登录的密码使用的,详情请看163的smtp说明

配置发送的邮箱和密码,注意不是你的邮箱登录密码。

# vi /etc/mail.rc

在底部添加:
set from="xxx@163.com"
set smtp=smtp.163.com
set smtp-auth-user=xxx@163.com
set smtp-auth-password=自己填写的授权码
set smtp-auth=login

测试发送

echo -e “This is a fine test body…” | mail -s “TestMail” xxx@163.com

为帮助您熟悉使用 SMTP 协议发送邮件的流程,提供以下 telnet 命令会话过程示例,来描述 SMTP 命令会话过程。

备注:其中 S 代表服务器,C 代表客户端。可以使用 Linux 命令 echo -n Content|base64 进行 base64 编码。

$telnet smtpdm.aliyun.com 25
S:220 163.com Anti-spam GT for Coremail System (163com[20141201])
C:EHLO test.com
S:250 OK
C:AUTH LOGIN
S:334 dXNlcm5hbWU6
C:YSoqKkBleGFtcGxlLm5ldA==         备注:用户名a***@example.net的base64编码
S:334 UGFzc3dvcmQ6
C:dGVzdA==                     备注:用户密码test的base64编码
S:235 Authentication successful
C:MAIL FROM: <a***@example.net>   备注:注意用 <> 将发件人扩起来
S:250 Mail Ok
C:RCPT TO: <a***@example.net>
S:250 Rcpt Ok
C:DATA
S:354 End data with <CR><LF>.<CR><LF>
C:subject: test
C:from: <a***@example.net>
C:to: <a***@example.net>
C:
C:test
C:.
S:Data Ok: queued as freedom ###envid=148316944
C:QUIT
S:221 Bye

了解SMTP错误代码

电子邮件发送过程并不总是像上面我们的电子邮件服务器聊天的例子那样顺利。反弹、阻止或其他问题可能会阻止发送电子邮件。在这种情况下,接收服务器可以使用SMTP错误代码通知您问题,了解它们的含义可以帮助您诊断和修复电子邮件传递障碍。

例如,以下是两组经常出现的SMTP错误:

4.X.X持续瞬态故障:这些错误代码以数字“4”开头,后面跟着另外两个数字。它们通常意味着邮件服务器出现临时故障。再次重复该命令可以消除错误,但服务器经常使用这些代码来阻止不受信任的发件人。

5.X.X永久错误:这些错误代码以数字“5”开头,后面跟着两个数字。它们通常表示SMTP连接已断开。如果你试图重新发送电子邮件,很可能仍然会导致同样的错误。

#define SMTP_SERV_NOSERVICE 421 /* Server error: <domain> Service not available, closing transmission channel */
#define SMTP_SERV_NOMAILBOX 450 /* Server error: Requested mail action not taken: mailbox unavailable */
#define SMTP_SERV_ACTABORT	451 /* Server error: Requested action aborted: local error in processing */
#define SMTP_SERV_NOSTORAGE 452 /* Server error: Requested action not taken: insufficient system storage */
#define SMTP_SERV_NOTLS		454 /* Server error: TLS not available */
#define SMTP_SERV_SYNTAX	500 /* Syntax error, command unrecognised */
#define SMTP_SERV_SYNTAX_P	501 /* Server error: Syntax error in parameters or arguments*/
#define SMTP_SERV_UNKNOWN	502 /* Server error: Unknown command */
#define SMTP_SERV_BADSEQ	503 /* Server error: Bad sequence of commands */
#define SMTP_SERV_NCMDPAR	504 /* Server error: Command parameter not implemented */
#define SMTP_SERV_NOACCMAIL	521 /* Server error: <domain> does not accept mail (see rfc1846) */
#define SMTP_SERV_STARTTLS  530 /* Server error: Start TLS needed */
#define SMTP_SERV_AUTHERR	535 /* Server error: Authentication failed */
#define SMTP_SERV_NOMBOXNM	550 /* Server error: Requested action not taken: mailbox unavailable */
#define SMTP_SERV_USRNOLOCL 551 /* Server error: User not local; please try <forward-path> */
#define SMTP_SERV_EXCSTOR	552 /* Server error: Requested mail action aborted: exceeded storage allocation */
#define SMTP_SERV_MBXNMNALL 553 /* Server error: Requested action not taken: mailbox name not allowed */
#define SMTP_SERV_TMUNKCOM  554 /* Server error: Transaction failed*/

SMTP与其他电子邮件协议有何不同?

回想一下SMTP的定义,你会记得我们说过它是许多电子邮件协议之一。POP和IMAP是另外两种最常用的电子邮件协议。

这些协议之间的主要区别在于,SMTP是将电子邮件从一个未知的邮件服务器发送或“推送”到另一个未知邮件服务器的唯一协议。POP和IMAP是用于从自己的邮件服务器接收或“拉取”收件人邮件的协议。因此,POP和IMAP仅限制将邮件传输到经过验证的邮件服务器。它们不能用于您自己网络之外的通信。

发送过程中的不同协议:SMTP用于发送电子邮件,POP和IMAP用于接收邮件

下面,我们将更深入地解释POP和IMAP的工作原理以及它们与SMTP的区别。

POP

POP代表邮局协议,用于接收传入消息。最新的版本是POP3,上次更新是在1988年。

这个协议之所以得名,是因为它的运作方式就像数字领域中现实生活中的邮局。POP3将接收电子邮件,并为客户保留这些电子邮件,直到他们收到为止。所有电子邮件都下载并存储在本地,这对于只使用一台计算机查看电子邮件的人来说是一个方便的解决方案。它也被企业普遍使用,因此员工可以在离线时查看电子邮件。

POP和SMTP有何不同?

SMTP是一种消息传输协议,而POP是一种邮件访问协议。换句话说,SMTP用于将邮件从一个用户发送到另一个用户,而POP用于接收电子邮件。

SMTP使用两次:一次是在发件人和电子邮件服务器之间建立连接并发送信息时,第二次是在发送信息并连接到收件人时。POP在接收者和他们的邮件服务器之间只使用一次。

IMAP

IMAP代表Internet邮件访问协议。简而言之,IMAP将邮件存储在电子邮件服务器上,但用户可以访问该服务器来检查和配置他们的电子邮件。这与POP的区别在于IMAP使用云服务器,因此任何设备都可以对电子邮件进行身份验证和分类。许多电子邮件用户更喜欢IMAP而不是POP,因为它既方便又高效。

IMAP和SMTP有何不同?

SMTP是一种消息传输协议,而IMAP是一种邮件访问协议(与POP类似)。因此,当SMTP发送邮件并处理传出的电子邮件时,IMAP只检索邮件并处理传入的电子邮件。

SMTP简单邮件传输协议(C/C++ 发送电子邮件)


int smtp_init(SMTP_Client **smtp);

int smtp_free(SMTP_Client **smtp);

int smtp_connect(SMTP_Client *smtp, const char *smtpHostName, const unsigned short smtpPort, int security);

int smtp_close(SMTP_Client *smtp);

ssize_t smtp_createLetter(SMTP_Client *smtp,
                          int textFormat,
                          const char *fromName, const char *fromMail,
                          const char *toName,   const char *toMail,
                          const char *mailSubject, const char *mailBody);

ssize_t smtp_attachFile(SMTP_Client *smtp, const char *filePath);

ssize_t smtp_endLetter(SMTP_Client *smtp);

int smtp_login(SMTP_Client *smtp, const char *smtpLogin, const char *smtpPasswd);

int smtp_sendLetter(SMTP_Client *smtp);


static ssize_t smtp_sendData_real(const char *file, int line, SMTP_Client *smtp, const unsigned char *data, size_t size)
{
    if(smtp->debugPrint)
    {
        char *duped = strdup((const char*)data);
        removeEndlEnding(duped);
        fprintf(smtp->debugStream, "[%s][%d] OUT>>: %s\n", file, line, duped);
        free(duped);
    }
    if(smtp->p->ssl)
        return smtp_sslSend(smtp, data, size);
    else
        return socketWrite(smtp->p->socketFd, data, size);
}

static ssize_t smtp_recvData_real(const char *file, int line, SMTP_Client *smtp, unsigned char *data, size_t size)
{
    ssize_t ret = 0;
    if(smtp->p->ssl)
        ret = smtp_sslRecv(smtp, data, size);
    else
        ret = socketRead(smtp->p->socketFd, data, size);
    if(smtp->debugPrint)
    {
        char *duped = strdup((const char*)data);
        removeEndlEnding(duped);
        fprintf(smtp->debugStream, "[%s][%d] IN <<: %s\n", file, line, duped);
        free(duped);
    }
    return ret;
}

static int recvStatus(SMTP_Client *smtp, const unsigned char *recvString)
{
...
    if(smtp->debugPrint)
        fprintf(smtp->debugStream, "[%s][%d] status = %d\n", __FILE__, __LINE__, atoi(statusStr));

    switch(reply)
    {
    case 250: case 235: case 354: case 334: case 221: break;
    default:
        if(smtp->debugPrint)
        {
            fprintf(smtp->debugStream, "Received status is an error!");
        }
        return -1;
    }

    return 0;
}

int main()
{
    ssize_t ret;
    SMTP_Client *smtp;

    int security = SMTP_NONSECURE;
    const char *smtpServer     = SMTP_SAMPLE_HOSTNAME;
    const char *smtpLogin      = SMTP_SAMPLE_LOGIN;
    const char *smtpPassword   = SMTP_SAMPLE_PASSWORD;

    const char *letterSubj     = "Hello :3";
    const char *letterBody     = "this is test!, <b>My Little Vixie!</b>! <span style=\"font-size: 50px;\">:3</size><br>";

    if(smtp_init(&smtp) < 0)
    {
        fprintf(stderr, "Can't initialize SMTP!\n");
        return 1;
    }

    /* 要打开调试输出,请设置这些标志 */
    smtp->debugPrint  = 1;
    smtp->debugStream = stderr;

    /* 初始化数据 */
    ret = smtp_createLetter(smtp,
                            SMTP_TextHTML,
                            SMTP_SAMPLE_NAME_FROM, SMTP_SAMPLE_MAIL_FROM,
                            SMTP_SAMPLE_NAME_TO, SMTP_SAMPLE_MAIL_TO,
                            letterSubj, letterBody);
    #if SMTP_SAMPLE_USE_SSL
        security = SMTP_SSL;
    #endif

    if(smtp_connect(smtp, smtpServer, SMTP_SAMPLE_PORT, security) < 0)
    {
        fprintf(stderr, "connect FAILED ... [%s]\n", smtp->errorString);
        smtp_free(&smtp);
        return 1;
    }

    printf("connect OK ...\n");

    ret = smtp_login(smtp, smtpLogin, smtpPassword);
    if(ret < 0)
    {
        fprintf(stderr, "auth FAILED ... [%s]\r\n", smtp->errorString);
        smtp_free(&smtp);
        return 1;
    }
    printf("auth OK ...\n");

    ret = smtp_sendLetter(smtp);
    if(ret < 0)
    {
        fprintf(stderr, "send FAIL ... [%s]\n", smtp->errorString);
        smtp_free(&smtp);
        return 1;
    }
    printf("send OK ...\n");

    smtp_free(&smtp);

    return 0;
}

运行结果:

总结

SMTP代表简单邮件传输协议。SMTP是一套交互准则,允许软件通过互联网传输电子邮件,称为简单邮件传输协议。

SMTP的主要目标是用于设置服务器之间的通信规则。服务器有一种识别自己的方式,并宣布他们试图执行什么样的通信。他们还有一种处理错误的方法,例如错误的电子邮件地址。例如,如果收件人地址错误,则会收到带有某种错误消息的服务器回复。

参考:rfc821.txt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/608318.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jmeter安装及使用

jmeter安装及使用 一、说明二、安装2.1 目录结构 三、使用3.1 运行jmeter3.2 设置语言3.3 设置线程组3.3.1 设置压测请求3.3.2 设置汇总报告3.3.3 设置结果树 3.4 开始压测 四、导出执行报告4.1 保存配置4.2 执行命令4.3 生成报告常见问题 一、说明 最近需要对项目接口进行压测…

vue简单实现一个类似微信左右滑动更多功能

1、需求背景 产品需要在购物车加一个左右滑动更多的功能&#xff0c;由于是PC端&#xff0c;大致扫描了下使用的UI库&#xff0c;貌似没有单独提供此类组件&#xff0c;反正有时间&#xff0c;就自己造一个轮子试试 2、先看效果 大致有一个橡皮筋的效果&#xff0c;可能没那…

分布式锁方案学习

很久没有写文章了&#xff0c;前些天的面试被问到了分布式锁的解决方案&#xff0c;回答的比较简单&#xff0c;只知道Redis&#xff0c;Mysql&#xff0c;Zookeeper能够作为分布式锁应用&#xff0c;今天就来详细的学习一下这三种分布式锁的设计思想及原理。 能够来看这篇文章…

05WEB系统的通信原理图

WEB系统的通信原理 名称作用URL统一资源定位符, 例如:http://www.baidu.com域名在https://www.baidu.com/这个网址中www.baidu.com 是一个域名IP地址计算机在网络当中的一个身份证号, 在同一个网络当中IP地址是唯一的, 有了IP地址两台计算机直接才能建立连接通信端口号一个计算…

如何让你的汇报更有说服力?数据监控是关键!

第5讲中玩过一个扫雷游戏&#xff0c;目标是排除计划中的“延期地雷”&#xff0c;但是&#xff0c;总有些“雷”防不胜防。我们在做计划的时候&#xff0c;明明已经想得非常周全了&#xff0c;可是&#xff0c;真正开工几天之后才发现&#xff0c;很多事情并没有那么简单。 1…

4-1 活动安排问题

1.什么是贪心算法 我的理解&#xff1a; 贪心算法是一种常用的问题求解方法&#xff0c;它在每个步骤上都选择当前看起来最优的解&#xff0c;而不考虑整体的最优解。简单来说&#xff0c;贪心算法采取局部最优的决策&#xff0c;希望通过每个局部最优解的选择&#xff0c;最终…

网络安全面试题大全(整理版)500+面试题附答案详解,最全面详细,看完稳了

前言 随着国家政策的扶持&#xff0c;网络安全行业也越来越为大众所熟知&#xff0c;想要进入到网络安全行业的人也越来越多。 为了拿到心仪的Offer之外&#xff0c;除了学好网络安全知识以外&#xff0c;还要应对好企业的面试。 作为一个安全老鸟&#xff0c;工作这么多年&…

全网最全的网络安全技术栈内容梳理(持续更新中)

前言 本文篇幅比较长~~耐心看完哦~ 网络安全真的那么好吗 据我了解现在我国网络安全人才缺口相当大&#xff0c;预计在2023年这方面人才缺口达到327万&#xff0c;我每年这方面的大学生才2W多。现在各政企都在发展数字化变革&#xff0c;对网络安全方面人才也是垂涎若渴&…

【31】核心易中期刊推荐——电子信息技术计算机技术

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

06SpringCloud rabbitmq安装

rabbitmq安装 说明&#xff1a;请使用资料里提供的CentOS-7-x86_64-DVD-1810.iso 安装虚拟机. 1. 安装依赖环境 在线安装依赖环境&#xff1a; yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel …

动态规划-概率DP

Bag of mice 题面翻译 https://www.luogu.com.cn/problem/CF148D 袋子里有 w w w 只白鼠和 b b b 只黑鼠 &#xff0c;A和B轮流从袋子里抓&#xff0c;谁先抓到白色谁就赢。A每次随机抓一只&#xff0c;B每次随机抓完一只之后会有另一只随机老鼠跑出来。如果两个人都没有抓到…

【小沐学GIS】基于Cesium实现三维数字地球Earth(CesiumJS入门安装)

文章目录 1、简介1.1 平台1.1.1 Cesium ion1.1.2 CesiumJS1.1.3 Cesium for Unity1.1.4 Cesium for Unreal1.1.4 Cesium for Omniverse1.1.5 Cesium for O3DE 1.2 支持的数据格式 2、CesiumJS安装3、代码测试3.1 安装node3.2 安装依赖项3.3 运行测试示例3.4 注册获取token 4、扩…

常见的前端框架

随着前端行业的发展&#xff0c;前端框架越来越多出现&#xff0c;为我们的项目开发工作带来了极大的便利&#xff0c;那目前主流的前端框架有哪些呢&#xff1f; 工作中我们常用的前端框架有vue框架、React框架、Bootstrap框架、Angular框架等&#xff0c;下面给大家简单介绍…

【AI绘图】二、stable diffusion环境准备与安装

前一篇&#xff1a;一、stable diffusion的发展史 放一张SD的效果图 硬件配置要求 Stable Diffusion是使用显卡生成图片&#xff0c;对电脑硬件有一定要求。 电脑配置最核心的关键点&#xff1a;看显卡、看内存、看硬盘、看 CPU。 显卡&#xff1a;N 卡&#xff08;英伟达 N…

基于内点法求解最优潮流研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Spring源码(二)— AbstractApplicationContext

上一篇文章简单的介绍了一下Spring框架大体的一个执行流程&#xff0c;整个专栏的内容也会根据第一篇序言中的流程图一步一步的向下梳理&#xff0c;并会慢慢补充更多的细节进去。 Test 创建ClassPathXmlApplicationContext来解析xml。 public class Test {public static vo…

剖析 OpenShift 中的 DNS

深入分析 OpenShift 内部 DNS OpenShift 中的DNS 相关组件及其配置1.1 Pod 中的 DNS 配置1.2 Pod 所在宿主机上的 DNS 配置及服务1.2.1 resolv.conf 文件 DNS 配置DNS 查询流程为什么需要内部 DNS&#xff1f; 本文基于 OpenShift 3.11&#xff0c;Kubernetes 1.11 进行测试 O…

2023/6/4周报

目录 摘要 论文阅读 1、标题和现存问题 2、使用GNN进行文本分类 3、INDUCT-GCN 4、实验准备 5、实验结果 深度学习 1、时空图的种类 2、图在环境中的应用 3、STGNN 总结 摘要 本周在论文阅读上&#xff0c;阅读了一篇InducT-GCN:归纳图卷积文本分类网络的论文。基…

python-pandas按各种时间统计和案例

使用到的库 pandas、matplotlib、numpy 使用到的函数 df.resample(“H”).sum() 参数 B business day frequency C custom business day frequency (experimental) D calendar day frequency W weekly frequency M month end frequency BM business month end frequency CBM…

【奶奶看了都会】云服务器ChatGLM模型fine-tuning微调,让你拥有自己的知识库

1.背景 大家好啊&#xff0c;上次给大家写了ChatGLM-6B的部署使用教程&#xff0c;【奶奶看了都会】云服务器部署开源ChatGLM-6B&#xff0c;让你拥有自己的ChatGPT 但是因为模型比较小的问题&#xff0c;所以日常工作中可能用不上。而且大家更希望的是模型能训练自己的数据&…