• SMTP邮件传输协议发送邮件和附件(转)


    1.     SMTP 常用命令简介

    1). SMTP 常用命令

    HELO/EHLO 向服务器标识用户身份

    MAIL 初始化邮件传输

    mail from:

    RCPT 标识单个的邮件接收人;常在MAIL 命令后面

    可有多个rcpt to:

    DATA 在单个或多个RCPT 命令后,表示所有的邮件接收人已标识,并初始化数据传输,以. 结束。

    VRFY 用于验证指定的用户/ 邮箱是否存在;由于安全方面的原因,服务器常禁止此命令

    EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用

    HELP 查询服务器支持什么命令

    NOOP 无操作,服务器应响应OK

    QUIT 结束会话

    RSET 重置会话,当前传输被取消

    如你对SMTP 命令不了解,可以用telnet 命令登陆到smtp 服务器用help 命令进行查看:

    220 tdcsw.maintek.corpnet.asus ESMTP Sendmail 8.13.8/8.13.8; Sat, 9 Jan 2010 10:
    45:09 +0800
    help
    214-2.0.0 This is sendmail
    214-2.0.0 Topics:
    214-2.0.0       HELO    EHLO    MAIL    RCPT    DATA
    214-2.0.0       RSET    NOOP    QUIT    HELP    VRFY
    214-2.0.0       EXPN    VERB    ETRN    DSN     AUTH
    214-2.0.0       STARTTLS
    214-2.0.0 For more info use "HELP <topic>".
    214-2.0.0 To report bugs in the implementation see
    214-2.0.0       http://www.sendmail.org/email-addresses.html
    214-2.0.0 For local information send email to Postmaster at your site.
    214 2.0.0 End of HELP info

    2).SMTP 返回码含义

      *   邮件服务返回代码含义 

      *   500   格式错误,命令不可识别(此错误也包括命令行过长) 

      *   501   参数格式错误 

      *   502   命令不可实现 

      *   503   错误的命令序列 

      *   504   命令参数不可实现 

      *   211    系统状态或系统帮助响应 

      *   214   帮助信息 

      *   220     服务就绪 

      *   221     服务关闭传输信道 

      *   421     服务未就绪,关闭传输信道(当必须关闭时,此应答可以作为对任何命令的响应) 

      *   250   要求的邮件操作完成 

      *   251   用户非本地,将转发向 

      *   450   要求的邮件操作未完成,邮箱不可用(例如,邮箱忙) 

      *   550   要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问) 

      *   451   放弃要求的操作;处理过程中出错 

      *   551   用户非本地,请尝试 

      *   452   系统存储不足,要求的操作未执行 

      *   552   过量的存储分配,要求的操作未执行 

      *   553   邮箱名不可用,要求的操作未执行(例如邮箱格式错误) 

      *   354   开始邮件输入,以. 结束 

      *   554   操作失败 

      *   535   用户验证失败 

      *   235   用户验证成功 

      *   334   等待用户输入验证信息 for next connection>;

    3) SMTP 命令应用

    我们下需使用telnet 命令实现smtp 邮件的发送,具体操作如下:

    220 tdcsw.com ESMTP Sendmail 8.13.8/8.13.8; Wed, 23 Dec 2009 18
    :18:18 +0800
    HELO tdcsw
    250 tdcsw.com Hello x-128-101-1-240.ahc.umn.edu [128.101.1.240], pleased to meet you
    MAIL FROM:lily@tdcsw.com
    250 2.1.0 lily@tdcsw.com... Sender ok
    RCPR TO:sam@163.com
    250 2.1.5 carven@tdcsw.pegatroncorp.com... Recipient ok
    DATA
    354 Enter mail, end with "." on a line by itself
    SUBJECT:HELLO
    HI:
    HAR are you?
    .
    250 2.0.0 nBNAIIG4000507 Message accepted for delivery
    quit
    221 2.0.0 tdcsw.maintek.corpnet.asus closing connection
    Connection to host lost.

    2.     用C++ 实现Mail 发送

    为了便于理解, 在此就不封装Mail 类了, 而是以过程式函数方式给出.

    1). 首先需要建立TCP 套接字, 连接端口依服务器而定,SMTP 服务默认端口为25, 我们以 默认端口为例

    WSADATA wsaData;

    int  SockFD;

    WSAStartup(MAKEWORD(2,2), &wsaData);

    SockFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    ServAddr.sin_family = AF_INET;

    ServAddr.sin_addr.s_addr = inet_addr (“192.168.1.1”);             //192.168.1.1 为服务器地址

    ServAddr.sin_port = htons(25);

    connect(SockFD, (struct sockaddr *)&ServAddr, sizeof(ServAddr));

    2). 发送SMTP 命令及数据

    const char HEADER[] = "HELO smtpSrv/r/n"

      "MAIL FROM: sender@126.com/r/n"

      "RCPT TO: recv@gmail.com/r/n"

      "DATA/r/n"

      "FROM: sender@126.com/r/n"

      "TO: recv@gmail.com/r/n"

      "SUBJECT: this is a test/r/n"

      "Date: Fri, 8 Jan 2010 16:12:30/r/n"

    "X-Mailer: shadowstar's mailer/r/n"

      "MIME-Version: 1.0/r/n"

      "Content-type: text/plain/r/n/r/n";

    //send HEADER

    send(SockFD, HEADER, strlen(HEADER), 0);

    const char CONTENT[]="this is content./r/n";

    //send CONTENT

    send(SockFD, CONTENT, strlen(CONTENT), 0);

    send(SockFD, "./r/n", strlen("./r/n"), 0);   //end

    send(SockFD, "QUIT/r/n", strlen("QUIT/r/n"), 0); //quit

    mail 发送的功能基本上就完成了, 当然, 如果是应用的话还是需要很多改动的地方的, 比如说添加附件等.

    3). 附件功能

    要使用SMTP 发送附件, 需要对SMTP 头信息进行说明, 改变Content-type 及为每一段正文添加BOUNDARY 名,示例如下:

    "DATA/r/n"

      "FROM: sender@126.com/r/n"

      "TO: recv@gmail.com/r/n"

      "SUBJECT: this is a test/r/n"

      "Date: Fri, 8 Jan 2010 16:12:30/r/n"

    "X-Mailer: shadowstar's mailer/r/n"

      "MIME-Version: 1.0/r/n"

      "Content-type: multipart/mixed; boundary=/"#BOUNDARY#/"/r/n/r/n";

    // 正文

    "--#BOUNDARY#/r/n"

      "Content-Type: text/plain; charset=gb2312/r/n"

      "Content-Transfer-Encoding: quoted-printable/r/n"

    邮件正文……….

    // 附件

    "/r/n--#BOUNDARY#/r/n"

      "Content-Type: application/octet-stream; name=att.txt/r/n"

      "Content-Disposition: attachment; filename=att.txt/r/n"

      "Content-Transfer-Encoding: base64/r/n"

      "/r/n"

    附件正信息(base64 编码)…..

    Base64 编码函数在网络上很容易找到, 这里就不给出源码了, 如需要支持HTML 格式而又不知道如何写这些头信息, 可以用outlook 或foxmail 写一封支持HTML 格式的mail, 查看其原文信息, 依照相同的格式发送就行了.

    4). 实现抄送及密送

    在SMTP 命令集中并没有RCPT CC 或RCPT BCC 相关命令, 那要如何来实现抄送和密送功能呢?

    在网络上找到这样一句话: “ 所有的接收者协商都通过RCPT TO 命令来实现,如果是BCC ,则协商发送后在对方接收时被删掉信封接收者”, 开始一直不明白这句话是什么意思? 后来通看查看foxmail 的邮件原文发现:

    Date: Wed, 6 Jan 2010 12:11:48 +0800

    From: "carven_li" < carven_li @smtp.com>

    To: "carven" <carven@smtp.com>

    Cc: "sam" <sam@smtp.com>,

      "yoyo" <yoyo@smtp.com>

    BCC: "clara" <clara@tsmtp.com>

    Subject: t

    X-mailer: Foxmail 5.0 [cn]

    Mime-Version: 1.0

    Content-Type: multipart/mixed;

        boundary="=====001_Dragon237244850520_====="

    才恍然大悟, 所谓的” 协商” 应该就是指发送方在Data 中指定哪些为CC, 哪些为BCC, 默认情况下什么都不写,只发送第一个RCPT TO 的mail, 其他的都被过滤掉.

  • 相关阅读:
    ZOJ 3556
    ZOJ 2836
    HDU 2841
    HDU 4135
    POJ 3695
    POJ 2773
    HDU 4407
    HDU 1796
    ZOJ 3688
    ZOJ 3687
  • 原文地址:https://www.cnblogs.com/sdgwc/p/3317420.html
Copyright © 2020-2023  润新知