Email協議小貼

來源:互聯網
上載者:User

Email協議
SMTP協議:
1 信件體:在RFC822中,是一系列的文本行
2 信頭:   結構較複雜,總的來說是由一些欄位組成,這些欄位為使用者和程式提供了關於信件的資訊,瞭解信頭就是弄清楚信頭的各個欄位。每個信頭欄位由一行或多行組成,對於跨多行的欄位,附加行以一個空格開始作為續行。
Field-name(欄位名)由一系列可以列印的US-ASCII字元組成,除空格和":"外,大多數欄位名稱由一系列字母,數字,中間經常插入橫線符。

步驟:
     1 用戶端程式發送郵件到SMTP伺服器
     2 SMTP伺服器傳遞郵件到pop3接受伺服器
     3 接受郵件用戶端從pop3上接受
     (MPTP簡易郵件傳輸通訊協定,POP3郵局協議)
標準欄位:
1 from:表述產生這個信件的人,通常含有一個信箱(From:XX@CC.com)
2 sender:用於指示信件寄件者與信件建立者是否不同(From:XXX@CC.net and Sender:XXX@CC.net) 並不一  樣
3 Reply-To:用於控制信件要回複的目的地
4 To:信件的主要收信人
5 Cc:信件的輔收信人
6 Bcc:密件副本的縮寫
7 Message-IDL用於一個信件的唯一標誌,有SMTP伺服器產生
8 Date含有電子郵件的建立日期和時間
9 Received:為信件的一個特定的郵件投遞伺服器記錄
10重發欄位(Resent-*)
11Subject用於描述信件的主題
12Comments用於吧一個注釋添加到信件中
13擴充欄位..(X-Loop ,X-Mailer)
MIME對信頭欄位的擴充
 MIME 對RFC822的欄位補充了一些信頭欄位,這些欄位通常是在寄送電子郵件的軟體在建立電子郵件時產生的,接受電子郵件的軟體提取其中的欄位得到有用的資訊
MIME補充的信頭欄位:
MIME-Version欄位用於標誌使用的MIME版本號碼,這是為了將來增加版本號碼解決相容的問題。該欄位是MIME信件唯一必須要求出現的欄位。
目前只有一個MIME版本在使用,一般加入一下欄位:
MIME-Version: 1.0
Content-Type是MIME中的主要欄位,描述特定MIME實體中包含的資料。
這個欄位有3部分:前兩部分組成媒體類型和1個可選分號分開的參數列表。如:
Content-Type:text/plain;charset="us-ascii"
其中text是媒體類型主類別,plain指媒體類型的附加層次類別。charset="us-ascii"是可選的參數列表。又如: Content-Type:text/html;charset=gb2312
指定媒體的主類型是text,但常值內容是HTML格式檔案。使用字元集是GB2312。
 Content-Transfer-Encoding,許多資料格式可以包含在信件中允許的字元範圍之外的位元組值,而且含有超過允許長度的資料行。一些資料格式的定義甚至沒有行的概念。Content-Transfer-Encoding欄位解決這些問題.
該欄位有5個值:7bit,8bit,binary,base64和quoted-printable.每個值都不區分大小寫。符合MIME規範的郵件處理常式必須能對這些編碼正確處理
(1)7bit特點:
    編碼長度不超過998位元組的資料,且該資料以Crlf結束的行組成 .為預設編碼,如果不提供Content-Transfer-Encoding欄位,就認為是7bit編碼
(2)8bit特點:
    與7bit一樣但允許US-ASCII 0
(3)binary編碼用於任意二進位8位元據,對行長度和允許的字元沒有限制。在MIME信件實體裡包含這種資料是不合法的,它僅僅是告訴指定資料的資料類型,而資料不是給隨郵件作為郵件內容發送的。
(4)base64特點:
     把位元據編碼成適合通過internet傳送的格式,在處理位元據作為郵件實體內容發送時,這種編碼方式應用的最為廣泛
 在base64編碼過程中要注意:
         1:編碼後的文本每行的長度:郵件的文本行每行應該控制在76個字元以內,如果超過需插入Crlf(斷行符號換行)。插入的Crlf不需要編碼
         2填充字元
  (1)quoted-printable編碼有文本組成的資料,在行超過80個字元的情況下很有用
  (2)x-uuencode 常用在MIME實體中進行標誌
5 MIME 媒體類型
 Connect-Type是用於在信頭中指定媒體類型的欄位,是MIME對RFC822擴充的主要信頭欄位
 Connect-Type: 媒體類型主類別/媒體類型的附加層次類別+有可選分號分開的參數列表。
一共有8個頂層的媒體類型:Text,Image,Audio,Video,Application,Message和Multipart.這些主要類型為他們各自的資料提供了一個結構
(1)Text
 Text類型用於指示基於文本的內容。這裡類別中任何子類型都不需要程式格式化資料而進行約定。參數有charset,用於指定Text所使用的字元集,預設時為US-ASCII.如:
Content-Type:text/plain;charset=us-ascii與Content-Type:text/plain是一樣的
Text的附加層次媒體類型還有:Plain, Enrich,Html等
   1 TEXT:
    text/plain 媒體類型標識有普通可列印字元組成,可以是US-ASCII,也可以是漢字,這些資料沒有經過格式化,直接瀏覽閱讀即可.
    text/enrich 為建立有對齊,顏色和字型變化功能的文本提供了一個簡單的標記語言。
    text/Html
   2 Image,Audio和Video
    這幾個媒體的主要類別是相當直觀的,資料通常是二進位的,採用base64編碼
    Content-Type:Image/jpeg
    Content-Transfer-Encoding:base64
   3 Application: 該媒體類別含有與特定應用檔案格式有關的任何媒體類型。
    幾種附加層次類別:
     octet-stream ,Content-Type:Application/actet-stream
       Application/actet-stream指示一個實體中含有任意資料,當內容未知或者對資料沒有定義媒體類型時,通常使用它
     Postscript ,Content-Type:Application/Postscript
     Application/Postscript媒體類型用於標識一個實體的內容是Postscript代碼。因為     Application/Postscript實體含有可執行代碼,他的內容必須毫無損失的到達目的地,也許是這個原因,通常使用quoted-printable編碼,是他不至於因為長度限制或在通過Internet網關時被破壞
    Message 這個媒體類型的主類別指定信體組成的實體
    RFC822,Content-Type:message/RFC822
    message/RFC822類型提供在一個信件中打包另外一個信件的簡單方法。所有符合MIME的郵件處理常式都必須支援這種類型的分析
    Partial,Content-Type:message/Partial
    message/Partial媒體類型指定了一種方法,該方法把大的實體分成多個組件,每個組件可以分開傳輸在接受端組裝,在發送和傳輸郵件的伺服器之間有信件尺寸限制的情況下,這種方法可以傳送比較大的信件
    External-body,content-type:message/External-body
    message/External-body表示實體含有的資料並不在信件內容裡,而僅僅是描述了一種從外部取出資料的方式。
    Multipart,Content-Type:mulipart/mixed
     Multipart媒體類型的主類別表示多個實體打包到單個實體,多組件實體由一個可選的前置,一個或多個信件體組件(每個前面有一個邊界行)和一個可選的結尾組件組成。邊界行由兩個橫線後跟一個邊界字串組成。這個邊界字串由Content-Type欄位中的參數boundary的值指定

SMTP會話:
特點:
    1 全過程發送文本完成,互動式請求接聽模式
    2 命令是文本形式的命令
    3 伺服器總返回一定的相應碼,表示用戶端的請求是否被正確的回答
    4 會話過程有一定的順序
補充:
  1 Email通訊是基於TCP/IP協議,要首先用WinSock建立和SMTP伺服器的串連
  2 串連成功後,要進行會話,SMTP有其認識的一整套命令,當然是事先約定好的,SMTP協議的很重要的一    部分就是會話的標準命令
  3 不過駭心命令不多,甚至幾個就能完成會話

一個簡單的會話 例子:
   1:AfxSocketInit(NULL)
   2:m_Socket.Create()
   3:m_Socket.Connect(LPCSTR(temp),25)
   4:virtual void OnReceive(int nErrorCode);等待伺服器回應接受m_Socket.Receive(sBuffer,sizeof    (sBuffer));
   5:發送m_Socket.Send("HELO smtp.sohu.com/r/n" ,len ) 返回4
   6:發送m_Socket.Send("MAIL FROM: mmnihao_@sohu.com/r/n" ,len ) 返回4
   7:發送m_Socket.Send("RCPT TO: mmnihao_@sohu.com/r/n" ,len ) 返回4
   8:發送m_Socket.Send("DATA/r/n" ,len ) 返回4 
   9:發送m_Socket.Send("text/r/n/r/n./r/n" ,len ) 返回4 (注意".")
   9:發送m_Socket.Send("QUIT/r/n" ,len ) 返回4   
   10 結束

程式:
  1定義一個CESocket類 繼承於CSocket負責相應接受資料訊息,CESocket初始化Init
  m_iCount 是一個命令發送的序號
//初始話
void CESocket::Init(CEmailSendDlg  *dlg)
{
 m_dlg=dlg;
 m_iCount=0;
}
CESocket接受資料相應函數OnReceive,調用主對話方塊的接受訊息處理函數,同時增加m_iCount
//接受資料響應函數,調用主對話方塊的接受訊息處理函數,同時增加m_iCount
void CESocket::OnReceive(int nErrorCode)
{

 m_dlg->ReceiveMessage(m_iCount);
  m_iCount++;
 CSocket::OnReceive(nErrorCode);
}

2:對話方塊的訊息處理函數:
void CEmailSendDlg::OnSend()
{

 GetDlgItemText(IDC_SMTP_ADDRESS,  m_sSendString[0]);
 GetDlgItemText(IDC_FROM_ADDRESS,  m_sSendString[1]);
 GetDlgItemText(IDC_TO_ADDRESS,  m_sSendString[2]);

 m_sSendString[0].TrimLeft(" ");
 m_sSendString[0].TrimRight(" ");
 m_sSendString[1].TrimLeft(" ");
 m_sSendString[1].TrimRight(" ");
 m_sSendString[2].TrimLeft(" ");
 m_sSendString[2].TrimRight(" ");
 
 if(m_sSendString[0].IsEmpty())
 {
  AfxMessageBox("請輸入SMTP伺服器位址(IP)");
  return;
 }
 if(m_sSendString[1].IsEmpty())
 {
  AfxMessageBox("請輸入你的EMail地址");
  return;
 }
 if(m_sSendString[2].IsEmpty())
 {
  AfxMessageBox("請輸入收件者的EMail地址");
  return;
 }

 m_sSendString[0]="HELO "+m_sSendString[0]+"/r/n";
 m_sSendString[1]="MAIL FROM: "+m_sSendString[1]+"/r/n";
 m_sSendString[2]="RCPT TO: "+m_sSendString[2]+"/r/n";

 m_sSendString[3]="DATA/r/n";
 
 GetDlgItemText(IDC_EMAIL_CONTENT,m_sSendString[4]);
 m_sSendString[4]=m_sSendString[4]+"/r/n/r/n./r/n";
 
 m_sSendString[5]="QUIT/r/n";

 CString temp;
 GetDlgItemText(IDC_SMTP_ADDRESS,temp);

 if(m_Socket.Connect(LPCSTR(temp),25)==FALSE)
 {
 }
 m_sReceivedData="";
}
當用戶端串連大SMTP伺服器後,smtp會發送一段歡迎碼然後用戶端和伺服器就可以按照SMTP命令進行會話
直到信件發送結束
void CEmailSendDlg::ReceiveMessage(int count)
{
 if(count>=6)
 {
  AfxMessageBox("Unknown Received Data");
  m_Socket.Close();
  return;
 }
 char sBuffer[255];
 int len=m_Socket.Receive(sBuffer,sizeof(sBuffer));
 sBuffer[len]=NULL;

 m_sReceivedData=m_sReceivedData+sBuffer;
 m_sReceivedData=m_sReceivedData+m_sSendString[count];

 m_Socket.Send(m_sSendString[count],m_sSendString[count].GetLength());

}

 

//----------------------------------------------
如何擷取從發信伺服器到網易MX伺服器的SMTP會話範例?字型: 小 中 大
  利用telnet手工類比一次smtp會話過程,能提供許多有用的資訊,從而協助我們迅速定位您的問題。下面這個手工smtp會話測試過程可以在多個作業系統下運行,包括Windows、Unix、和Linux。
  本協助講述了如果利用telnet來類比一次完整的發信。請將您的整個會話過程複製下來,並發送給我們。
  2nn開頭的返回碼,表示會話是正常的。而5nn或者4nn開頭的返回碼則表示有錯誤發生。
  注意:本測試過程必須在發信伺服器上進行。

  下面是具體步驟:
  1、開啟一個命令視窗,鍵入:
  telnet mx.mail.126.split.netease.com 25
  這條命令將建立一個到我們126郵件伺服器的串連。
  2、 鍵入:
  HELO yourdomain.com
  這裡的yourdomain.com指您的網域名稱。
  3、 鍵入:
  MAIL FROM:< you@yourdomain.com >(無需空格)
  這裡的you@yourdomain.com指您們域的一個郵箱名。
  注意:郵箱名需要用<>括起來。
  4: 鍵入:
  RCPT TO:< postmaster >(無需空格)
  這將發信到我們的postmaster郵箱。
  注意:郵箱名需要用<>括起來。
  5: 鍵入:
  DATA
  6: 輸入郵件的信頭和本文。
  FROM:< you@yourdomain.com>(無需空格)
  TO:< postmaster>(無需空格)
  SUBJECT: yourdomain.com to netease

  Hi!
  It's from yourdomain.com. Just a test.
  Bye.
  7: 新起一個空行,鍵入:
  .
  然後按斷行符號,這將結束整封信,並發送給伺服器

    

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.