久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 11307|回復: 1
打印 上一主題 下一主題
收起左側(cè)

簡單電子郵件SMTP協(xié)議解析

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:113276 發(fā)表于 2016-4-10 20:22 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
最近幾日學習了一下簡單電子郵件協(xié)議smtp的使用,并移植了smtp協(xié)議棧中的code,幾經(jīng)折返,最終成功實現(xiàn)郵件的發(fā)送。

一、SMTP協(xié)議流程
首先通過計算機的telnet或者TCPIP調(diào)試工具來輸入命令。我是使用TCP調(diào)試工具進行的驗證。

1、SMTP服務器網(wǎng)絡地址
首先去163郵箱注冊一個用戶,然后在郵箱里面設(shè)置去掉SSL并開啟SMTP的3個選項。之后就可以使用了,
就163郵箱來說他的服務器是smtp.163.com。為了和程序一致所以需要轉(zhuǎn)換為IP地址。通過DNS可以知道他的IP地址映射。
這樣就獲得了一個IP地址
2、SMTP服務器端口
SMTP默認的端口是 port =25
3、會話
使用TCP連接連接這個IP地址和25端口,連接成功之后服務器會發(fā)回來一串數(shù)如下
220 163.com Anti-spam GT for Coremail System (163com[20141201])
然后需要發(fā)送helo xxx命令發(fā)送完畢 ,否則他會返回503 Error: send HELO/EHLO first   xxx可以是個任意的名字他會返回
250 OK
表示完成握手接下來就是用戶名和密碼的認證了。需要你主動發(fā)送認證請求發(fā)送命令
auth login空格+回車
334 dXNlcm5hbWU6
這是表示提示輸入用戶名,
dXNlcm5hbWU6這個是用base64加密的username,然后輸入你的xxx@163.com,同樣的也需要轉(zhuǎn)換為BASE64碼,之后
334 UGFzc3dvcmQ6
這是表示提示輸入密碼了。同樣的
UGFzc3dvcmQ6表示password了輸入密碼******轉(zhuǎn)換為BASE64代碼,之后
235 Authentication successful
返回這個之后表示認證成功了,接下來就是發(fā)件人和收件人的email地址,然后依次輸入

mail from: <wjw890912@163.com>  +回車

rcpt to: <wjw890912@163.com> +回車

服務器都會回復250 Mail OK 來確認。接下來就是郵件的標題和正文了,輸入之

data
From:PC
To:XX163
Subject:Test for Smtp

The PC sent e-mail to here pass the SMTP.


.

最后的一個點時必要的。必須要。最后輸入quit命令,就斷開連接退出了此次會話。一封電子郵件也就被發(fā)到了郵箱中了。可以在郵箱中看到發(fā)送的內(nèi)容。


二、代碼移植和修改

已經(jīng)通過TCP工具進行了模擬,只要按照這個流程就可以用程序把人發(fā)的變成自動發(fā)。首先gitHub拿到代碼后找到smtp.c和smtp.h倆文件。加入到project 中設(shè)置C/C++ 中include paths 。 找到API接口重寫那個接口函數(shù)

    smtp_set_server_addr("220.181.12.18");//smtp.163.com
    smtp_set_auth("wjw890912@163.com","**************");//密碼和用戶名使用明文即可,系統(tǒng)自動轉(zhuǎn)碼
    smtp_send_mail("wjw890912@163.com", "wjw890912@163.com", "Reporter",  "The MCU sent e-mail to                                     here pass the  SMTP", my_smtp_result_fn,0 );

并添加一個回執(zhí)函數(shù)my_smtp_result_fn
void my_smtp_result_fn(void *arg, u8_t smtp_result, u16_t srv_err, err_t err)
  {                       
   printf("mail (%p) sent with results: 0x%02x, 0x%04x, 0x%08x\n", arg, smtp_result, srv_err, err);
}
這是一個發(fā)送完成回執(zhí)事件,發(fā)送完成后無論成功與否都會返回一個smtp_result,根據(jù)這個值應用程序作出相應的反應了。

最后編譯下載到目標板中執(zhí)行

在debug的過程中發(fā)現(xiàn)這個程序并不能發(fā)出正確的郵件,于是對這個文件中的代碼稍微看了一下,
首先是程序的框架,首先他會建立一個描述
所謂的smtp session,用來記錄所有的有關(guān)系的項結(jié)構(gòu)。然后調(diào)用TCP,創(chuàng)建一個用于連接的TCP PCB之后開始執(zhí)行SMTP的狀態(tài)機。最后結(jié)束發(fā)送完成事件,非正常就是直接發(fā)送完成事件。所以關(guān)鍵是SMTP的裝態(tài)機。代碼如下
switch(s->state)
  {
  case(SMTP_NULL):
    /* wait for 220 */
    if (response_code == 220) {
      /* then send HELO */
      next_state = smtp_prepare_helo(s, &tx_buf_len, pcb);
    }
    break;
  case(SMTP_HELO):
    /* wait for 250 */
    if (response_code == 250) {
#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN
      /* then send AUTH or MAIL */
      next_state = smtp_prepare_auth_or_mail(s, &tx_buf_len);
    }
    break;
  case(SMTP_AUTH_LOGIN):
  case(SMTP_AUTH_PLAIN):
    /* wait for 235 */
    if (response_code == 235) {
#endif /* SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN */
      /* send MAIL */
      next_state = smtp_prepare_mail(s, &tx_buf_len);
    }
    break;
#if SMTP_SUPPORT_AUTH_LOGIN
  case(SMTP_AUTH_LOGIN_UNAME):
    /* wait for 334 Username */
    if (response_code == 334) {
      if (pbuf_strstr(s->p, SMTP_RESP_LOGIN_UNAME) != 0xFFFF) {
        /* send username */
        next_state = smtp_prepare_auth_login_uname(s, &tx_buf_len);
      }
    }
    break;
  case(SMTP_AUTH_LOGIN_PASS):
    /* wait for 334 Password */
    if (response_code == 334) {
      if (pbuf_strstr(s->p, SMTP_RESP_LOGIN_PASS) != 0xFFFF) {
        /* send username */
        next_state = smtp_prepare_auth_login_pass(s, &tx_buf_len);
      }
    }
    break;
#endif /* SMTP_SUPPORT_AUTH_LOGIN */
  case(SMTP_MAIL):
    /* wait for 250 */
    if (response_code == 250) {
      /* send RCPT */
      next_state = smtp_prepare_rcpt(s, &tx_buf_len);
    }
    break;
  case(SMTP_RCPT):
    /* wait for 250 */
    if (response_code == 250) {
      /* send DATA */
      SMEMCPY(s->tx_buf, SMTP_CMD_DATA, SMTP_CMD_DATA_LEN);
      tx_buf_len = SMTP_CMD_DATA_LEN;
      next_state = SMTP_DATA;
    }
    break;
  case(SMTP_DATA):
    /* wait for 354 */
    if (response_code == 354) {
      /* send email header */
      next_state = smtp_prepare_header(s, &tx_buf_len);
    }
    break;
  case(SMTP_BODY):
    /* nothing to be done here, handled somewhere else */
    break;
  case(SMTP_QUIT):
    /* wait for 250 */
    if (response_code == 250) {
      /* send QUIT */
      next_state = smtp_prepare_quit(s, &tx_buf_len);
    }
    break;
  case(SMTP_CLOSED):
    /* nothing to do, wait for connection closed from server */
    return;


然后改成本地服務器進行模擬,發(fā)現(xiàn)流程是正常的但是系統(tǒng)打印的代碼是大寫,服務器不能識別,于是改成小寫
#define SMTP_CMD_AUTHLOGIN        "auth login \r\n"
#define SMTP_CMD_AUTHLOGIN_LEN    13
#define SMTP_CMD_MAIL_1           "mail from: <"
#define SMTP_CMD_MAIL_1_LEN       12
#define SMTP_CMD_MAIL_2           ">\r\n"
#define SMTP_CMD_MAIL_2_LEN       3
#define SMTP_CMD_RCPT_1           "rcpt to: <"
#define SMTP_CMD_RCPT_1_LEN       10
#define SMTP_CMD_RCPT_2           ">\r\n"
#define SMTP_CMD_RCPT_2_LEN       3
#define SMTP_CMD_DATA             "data\r\n"
#define SMTP_CMD_DATA_LEN         6
#define SMTP_CMD_HEADER_1         "From: <"
#define SMTP_CMD_HEADER_1_LEN     7
#define SMTP_CMD_HEADER_2         ">\r\nTo: <"
#define SMTP_CMD_HEADER_2_LEN     8
#define SMTP_CMD_HEADER_3         ">\r\nSubject: "
#define SMTP_CMD_HEADER_3_LEN     12
#define SMTP_CMD_HEADER_4         "\r\n\r\n"
#define SMTP_CMD_HEADER_4_LEN     4
#define SMTP_CMD_BODY_FINISHED    "\r\n.\r\n"
#define SMTP_CMD_BODY_FINISHED_LEN 5
#define SMTP_CMD_QUIT             "quit\r\n"
#define SMTP_CMD_QUIT_LEN         6
依次修改這些宏。
還有一個地方就是握手的回復上是250 OK而原作者寫的是auth 或者auth=,但是實際并不會返回這個而是OK,所以需要改成
#define SMTP_KEYWORD_AUTH_SP    "OK"

#define SMTP_AUTH_PARAM_LOGIN   "OK"
最后修改一下改為小寫即可
#define SMTP_CMD_EHLO_1           "helo ["
#define SMTP_CMD_EHLO_1_LEN       6
#define SMTP_CMD_EHLO_2           "]\r\n"
#define SMTP_CMD_EHLO_2_LEN       3
#define SMTP_CMD_AUTHPLAIN_1      "AUTH PLAIN "
#define SMTP_CMD_AUTHPLAIN_1_LEN  11
#define SMTP_CMD_AUTHPLAIN_2      "\r\n"
#define SMTP_CMD_AUTHPLAIN_2_LEN  2

并且關(guān)閉 A UTH PLAIN 開關(guān)#define SMTP_SUPPORT_AUTH_PLAIN   0

最后一件事就是把板子的IP地址調(diào)整為可以訪問外網(wǎng)的IP號段,否則防火墻會攔截這個試圖發(fā)送郵件的非法IP地址,導致發(fā)送失敗。我這里是0和254、253修改為0號段后就可以正常的發(fā)出郵件了!

最后的最后@163郵箱一天中有郵件限制。不能一直發(fā),2秒發(fā)一封這樣發(fā)不到200封郵件就會被限制,并返回錯誤。此時程序依舊是正常運行的只是服務器會返回中止的代碼而已。

如果要做應用把函數(shù)的輸入?yún)?shù)改為const char *ptr,然后指向一個數(shù)組并在末尾加‘\0’就可以把內(nèi)存引用出來作為信件內(nèi)容發(fā)送出去。比如送出個采集到的溫度值什么的,即可向郵箱完成一個小報告了。






分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:86450 發(fā)表于 2018-9-20 18:03 | 只看該作者
神奇的 東西!!!!!!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲免费在线观看 | 国产欧美久久精品 | 中文字幕在线观看视频一区 | 九九热这里只有精品6 | 91精品国产综合久久久久久丝袜 | 国产精品久久久久aaaa | 日韩精品视频在线免费观看 | 欧洲性生活视频 | 亚洲精品中文字幕av | 亚洲精品国产一区 | 中文字幕一级 | 激情福利视频 | 精品毛片在线观看 | 成人av电影天堂 | 久久久久亚洲视频 | www.99re| 亚洲一区二区三区免费在线观看 | 亚洲国产精品视频一区 | 精品国产乱码久久久久久闺蜜 | 天堂va在线观看 | 91精品综合久久久久久五月天 | 精品av久久久久电影 | 国产亚洲欧美日韩精品一区二区三区 | 狠狠ri | 亚洲视频在线播放 | 亚洲成人日韩 | 在线观看av网站永久 | 久久99精品久久久久蜜桃tv | 国产欧美一区二区精品久导航 | 一级片免费视频 | 午夜av电影 | 小早川怜子xxxxaⅴ在线 | 亚洲精品一区二区 | 成人国产精品色哟哟 | 中文字幕视频一区二区 | 91久久精品国产 | 午夜视频一区二区三区 | 日韩三| 亚洲精品久久久一区二区三区 | 翔田千里一区二区 | 国产一级免费在线观看 |