C和C#两种方式实现邮件的简单发送
内容为通过两种方式发送邮件--1.C语言发送邮件 2.C#发送邮件
一,C语言进行邮件的发送
C语言发送邮件的步骤的简单解析:
1.创建TCP连接 socket()
2.连接到邮箱服务器 SOCKADDR_IN,connect()
3.邮箱用户和密码认证登录 "EHLO smtp.163.com\r\n" → "AUTH LOGIN\r\n"
4.发送邮件主题内容
a.发送 "MAIL FROM:<"邮件的发送方地址">\r\n" //
b.发送 "RCPT TO:<"邮件接收方的地址">\r\n"
c.发送 "DATA\r\n"
d.发送邮件头(From,To,Subject,Date等),邮件体(邮件体可为空)
e.添加附件内容(可以添加多个,附件也可以不添加)
5.退出登录 发送 "QUIT\r\n"
6.关闭TCP连接 closesocket(connection);
C语言关键代码如下:
//创建TCP连接
1 if ((connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) 2 { 3 return INVALID_SOCKET; 4 }
//连接到邮箱服务器
1 void ConnectToServer(SOCKET connection,const char *serverName) 2 { 3 //设置SockAddr_In地址结构 4 SOCKADDR_IN serAddr; 5 serAddr.sin_family = AF_INET; 6 serAddr.sin_port = htons(SMTP_PORT); 7 //来自 CAsysSocket::Connect() 8 serAddr.sin_addr.s_addr = inet_addr(serverName); 9 if (serAddr.sin_addr.s_addr == INADDR_NONE) 10 { 11 LPHOSTENT lphost; 12 lphost = gethostbyname(serverName); 13 if (lphost != NULL) 14 serAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->S_un.S_addr; 15 else 16 return; 17 } 18 //连接服务器 19 connect(connection, (SOCKADDR *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR) 20 return; 21 }
//认证登录
1 //认证登录 2 BOOL AuthLogin(SOCKET connection, const char *serverName,const char *userAccount, const char *password) 3 { 4 //发送EHLO%SMTP-Server Name% 说明:HELO 是不带身份验证的,而 EHLO 是带身份验证 5 char szHello[PARA_BUF] = { 0 }; 6 sprintf(szHello, "EHLO %s\r\n", serverName); //"EHLO %s\r\n" 7 if (!send_rev(connection, szHello, GENERIC_SUCCESS)) 8 return FALSE; 9 10 //发送AUTH LOGIN 11 if (!send_rev(connection, "AUTH LOGIN\r\n", AUTHLOGIN_SUCCESS)) // "AUTH LOGIN\r\n" 12 return FALSE; 13 14 //发送经过Base64编码的用户账号 15 char szAccount[100]={0}; 16 base64_encode(userAccount, strlen(userAccount), &szAccount); //base64编码 17 strcat(szAccount, "\r\n"); 18 if (!send_rev(connection, szAccount, AUTHLOGIN_SUCCESS)) //账号 19 return FALSE; 20 21 //发送经过Base64编码的密码 22 char szPassword[100]={0}; 23 base64_encode(password, strlen(password), &szPassword); 24 strcat(szPassword, "\r\n"); 25 if (!send_rev(connection, szPassword, AUTH_SUCCESS)) //密码 26 return FALSE; 27 return TRUE; 28 }
//发送邮件(包含了用户的退出操作QUIT)
1 //发送邮件 2 BOOL SendMail(SOCKET connection,const char *from, const char *to, 3 const char *subject, const char *body, 4 const char *userName,const char *filePath) 5 { 6 char szFrom[PARA_BUF] = { 0 }; 7 char szTo[PARA_BUF] = { 0 }; 8 char szSubject[PARA_BUF] = { 0 }; 9 char szBodyHead[PARA_BUF * 10] = { 0 }; 10 char szBody[PARA_BUF * 20] = { 0 }; 11 12 char szDateTime[PARA_BUF] = { 0 }; 13 char *szContent=NULL; 14 //邮件的内容,包括正文文本信息,附件内容信息等 15 if (!chars_malloc(&szContent, MAX_FILE_SIZE*4/3 + M ) ) 16 { 17 return FALSE; 18 } 19 20 //发送Header中的Mail From 21 sprintf(szFrom, "MAIL FROM:<%s>\r\n", from); // MAIL FROM:<%s>\r\n 22 if (!send_rev(connection, szFrom, GENERIC_SUCCESS) ) 23 return FALSE; 24 25 //发送Header中RCPT TO 26 sprintf(szTo, "RCPT TO:<%s>\r\n", to); // RCPT TO:<%s>\r\n 27 if (!send_rev(connection, szTo, GENERIC_SUCCESS)) 28 return FALSE; 29 30 //发送DATA\r\n 31 if (!send_rev(connection, "DATA\r\n", DATA_SUCCESS)) // DATA\r\n 32 return FALSE; 33 34 //进行 Body 处理 35 sprintf(szFrom, "FROM:%s<%s>\r\n", userName, from); //content 36 sprintf(szTo, "TO:<%s>\r\n", to); 37 time_t ltime = time(NULL); 38 _tzset(); 39 sprintf(szDateTime, "Date:%s", ctime(<ime)); 40 sprintf(szSubject, "Subject:%s\r\n", subject); 41 42 sprintf(szBodyHead, "X_Mailer:ntSmtp[ch]\r\n", subject); 43 strcat(szBodyHead, "MIME_Version:1.0\r\n"); 44 strcat(szBodyHead, "Content- type:multipart/mixed;Boundary=ntSmtp\r\n\r\n"); 45 strcat(szBodyHead, "--ntSmtp\r\n"); 46 strcat(szBodyHead, "Content-type:text/plain;Charset=gb2312\r\n"); 47 strcat(szBodyHead, "Content_Transfer-Encoding:8bit\r\n\r\n"); 48 49 sprintf(szBody, "%s\r\n\r\n", body); 50 51 //连接成content的各部分内容 52 strcat(szContent, szFrom); 53 strcat(szContent, szTo); 54 strcat(szContent, szDateTime); 55 strcat(szContent, szSubject); 56 strcat(szContent, szBodyHead); 57 strcat(szContent, szBody); 58 59 if (filePath != NULL) 60 { //将附件内容添加到szContent 61 AppendAttachment( &szContent, filePath); 62 //AppendAttachment(&szContent, filePath); 63 } 64 //添加结束标记 65 strcat(szContent, "\r\n.\r\n"); // \r\n.\r\n 66 67 //发送Content 68 if ( !send_rev(connection, szContent, GENERIC_SUCCESS) ) 69 return FALSE; 70 71 //发送Quit,退出登录 72 if( !send_rev(connection, "QUIT\r\n", QUIT_SUCCESS) ) //"QUIT\r\n" 73 return FALSE; 74 75 free(szContent); 76 return TRUE; 77 }
二,C#进行邮件的发送
通过C#进行邮件的发送,不需要C语言那样必须把握住连接通信过程中的诸多细节,
如果进行简单的邮件发送,只需要使用到两个类,一个是MailMessage类,该类定义了
一封完整邮件多需要的信息(包括邮件的发送方,接收方,主题,正文内容,附件等信息),
另一个是SmtpClient类,该类是用于服务器端的操作,通过该类的对象,你就可以设置
邮箱服务器的地址(例如:smtp.163.com),邮箱的登录账号与密码等,最终通过该类
的对象便可以将MailMessage的信息发送到指定的邮箱了.
C#发送邮件的步骤的简单解析:
1.创建MailMessage对象,设置MailMessage的相关成员数据; 包括From,To,Subject,Body,Attachments等信息.
2.创建服务器端对象SmtpClient,设置服务器,邮箱账号,密码.
3.通过SmtpClient对象,将MailMessage邮件信息发送出去; 可以进行普通的发送以及异步发送(不阻塞线程).
C#关键代码如下:
//异步发送邮件
1 //发送按钮 2 private void btn_Send_Click(object sender, EventArgs e) 3 { 4 //创建MailMessage对象 5 MailAddress from = new MailAddress("ntsmtp@163.com"); 6 MailAddress to = new MailAddress("miaosha5s@sohu.com"); 7 MailMessage mailMessage = new MailMessage(from, to) ; 8 mailMessage.Subject="主题"; 9 mailMessage.Body="这是一封来自远方的邮件."; 10 11 Attachment attachment01 = new Attachment("E:\\01.jpg"); //附件 12 Attachment attachment02 = new Attachment("E:\\02.mp3"); 13 mailMessage.Attachments.Add(attachment01); 14 mailMessage.Attachments.Add(attachment02); 15 16 //创建SmtpClient对象 邮箱服务器smtp.163.com 17 SmtpClient smtpClient = new SmtpClient("smtp.163.com"); 18 smtpClient.UseDefaultCredentials = true; 19 smtpClient.Credentials = 20 new NetworkCredential("邮箱账号", "登录密码"); //邮箱认证登录 21 //smtpClient.Timeout = 5000; 22 try 23 { 24 //使用异步发送,不会阻塞该线程 25 smtpClient.SendCompleted += new //完成发送调用回调函数 26 SendCompletedEventHandler(SendCompletedCallback); 27 smtpClient.SendAsync(mailMessage, mailMessage); 28 } 29 catch(Exception ex) 30 { 31 mailMessage.Dispose(); //主动释放资源 32 smtpClient.Dispose(); 33 MessageBox.Show("发送失败! "+System.Environment.NewLine+ 34 "错误信息:"+ ex.Message); 35 } 36 return; 37 }
//异步发送完成的回调函数:
1 //异步发送邮件完成的回调函数 2 public static void SendCompletedCallback(object sender, 3 AsyncCompletedEventArgs e) 4 { 5 SmtpClient smtpClient = (SmtpClient)sender; 6 //MailMessage mailMessage = (MailMessage)e.UserState; 7 if (e.Cancelled) 8 { 9 MessageBox.Show("Send canceled."); 10 } 11 if (e.Error != null) 12 { 13 MessageBox.Show("错误信息: "+e.Error.ToString() ); 14 } 15 else 16 { 17 MessageBox.Show("Message Sent."); 18 smtpClient.Dispose(); 19 //mailMessage.Dispose(); 20 } 21 }
总结:通过两种方式实现了简单的邮件发送功能,从中可以比较这两种语言在实现上的差异性,
C语言的实现更加讲究流程和细节,你需要比较深的懂得网络的相关知识和SMTP的相关协议,
优点是可以更加直接的操作邮件的发送过程,缺点就是实现起来比较繁琐,容易异常.
C#的实现就更加简洁明了了,它封装了邮件发送过程中的很多细节,这些细节对用户来说并不是
必要的,使用者只需要知道几个重要的类(MailMessage,SmtpClient类)的使用,而且程序一般会比
C程序要来的稳定,不容易发生异常错误.
附:C语言实现邮件发送的程序代码借鉴自<Windows网络程序设计完全讲义>--作者:高守传