经过几天的努力,从完全不懂SMTP到折腾出个可以发送邮件内容和附件的DEMO。话少说,直接上代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO; namespace UtilSp.ClassLib
{
public class SmtpSp
{
#region Member #region boundary normal Property
private string boundary_ = Guid.NewGuid().ToString();//Generate unique boundary.
public string boundary_pro
{
get
{
return boundary_;
}
set
{
boundary_ = value;
}
}
#endregion #region exception Property
private Exception exception_ = null;
public Exception exception_pro
{
get
{
return exception_;
}
set
{
exception_ = value;
}
}
#endregion #region encoding_smtp normal Property
private Encoding encoding_smtp_ = Encoding.ASCII;//smtp encoding must be ascii.
private Encoding encoding_smtp_pro
{
get
{
return encoding_smtp_;
}
}
#endregion #region encoding_subject normal Property
private Encoding encoding_subject_ = Encoding.UTF8;
public Encoding encoding_subject_pro
{
get
{
return encoding_subject_;
}
set
{
encoding_subject_ = value;
}
}
#endregion #region encoding_content normal Property
private Encoding encoding_content_ = Encoding.GetEncoding("gb2312");
public Encoding encoding_content_pro
{
get
{
return encoding_content_;
}
set
{
encoding_content_ = value;
}
}
#endregion #region receiveInfo normal Property
private string receiveInfo_ = "";
public string receiveInfo_pro
{
get
{
return receiveInfo_;
}
set
{
receiveInfo_ = value;
}
}
#endregion #region socket normal Property
private Socket socket_;
public Socket socket_pro
{
get
{
return socket_;
}
private set
{
socket_ = value;
}
}
#endregion #endregion private sealed class SMTP_BACKS
{
public const string SERVER_READY_OK = "220";
public const string OPERATE_COMPLETE = "250";
public const string AUTH_LOGIN_OK = "334";
public const string USER_NAME_LOGIN_OK = "334";
public const string PASSWORD_LOGIN_OK = "235";
public const string DATA_OK = "354";
} private sealed class SMTP_CMD
{
public const string AUTH_LOGIN = "auth login\r\n";
public const string MAIL_FROM = "mail from:";
public const string RCPT_TO = "rcpt to:";
public const string SEND_BODY = "data\r\n";
public const string VERIFY = "ehlo hello\r\n";
} public sealed class MailInfo
{
#region attachments normal Property
private List<string> attachments_ = new List<string>();
public List<string> attachments_pro
{
get
{
return attachments_;
}
set
{
attachments_ = value;
}
}
#endregion #region content normal Property
private string content_ = "";
public string content_pro
{
get
{
return content_;
}
set
{
content_ = value;
}
}
#endregion #region password normal Property
private string password_ = "";
public string password_pro
{
get
{
return password_;
}
set
{
password_ = value;
}
}
#endregion #region receiverAddresses normal Property
private List<string> receiverAddresses_ = new List<string>();
public List<string> receiverAddresses_pro
{
get
{
return receiverAddresses_;
}
set
{
receiverAddresses_ = value;
}
}
#endregion #region senderAddress normal Property
private string senderAddress_ = "";
public string senderAddress_pro
{
get
{
return senderAddress_;
}
set
{
senderAddress_ = value;
}
}
#endregion #region subject normal Property
private string subject_ = "";
public string subject_pro
{
get
{
return subject_;
}
set
{
subject_ = value;
}
}
#endregion #region userName normal Property
private string userName_ = "";
public string userName_pro
{
get
{
return userName_;
}
set
{
userName_ = value;
}
}
#endregion
} #region send Function
public bool send(string mailHostIP, int port, MailInfo mailInfo)
{
try
{
exception_pro = null;
if (!isLegal(mailHostIP, port, mailInfo))
{
return false;
}
socket_pro = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket_pro.Connect(mailHostIP, port);
if (!socket_pro.Connected)
{
socket_pro.Close();
exception_pro = new Exception(Tip.ConnectFail);
return false;
} if (!isServerReady())
{
exception_pro = new Exception(Tip.ServerReadyFail + analyReceiveError());
socket_pro.Close();
return false;
} if (!verify())
{
exception_pro = new Exception(Tip.VerifyFail + analyReceiveError());
socket_pro.Close();
return false;
} if (!authLogin())
{
exception_pro = new Exception(Tip.AuthLoginFail + analyReceiveError());
socket_pro.Close();
return false;
} if (!userNameLogin(mailInfo.userName_pro))
{
exception_pro = new Exception(Tip.UserNameLoginFail + analyReceiveError());
socket_pro.Close();
return false;
} if (!passowrdLogin(mailInfo.password_pro))
{
exception_pro = new Exception(Tip.PasswordLoginFail + analyReceiveError());
socket_pro.Close();
return false;
} if (!mailFrom(mailInfo.senderAddress_pro))
{
exception_pro = new Exception(Tip.MailFromFail + analyReceiveError());
socket_pro.Close();
return false;
} if (!rcptTo(mailInfo.receiverAddresses_pro))
{
exception_pro = new Exception(Tip.RcptToFail + analyReceiveError());
socket_pro.Close();
return false;
} if (!sendMail(mailInfo))
{
exception_pro = new Exception(Tip.SendMailFail + analyReceiveError());
socket_pro.Close();
return false;
} socket_pro.Close();
return true;
}
catch (System.Exception ex)
{
exception_pro = ex;
return false;
}
} private string analyReceiveError()
{
if (string.IsNullOrEmpty(receiveInfo_pro))
{
return Tip.ReceiveInfoEmpty;
}
return receiveInfo_pro;
} #endregion private int socketSend(string sendStr)
{
byte[] sendBuffer = encoding_smtp_pro.GetBytes(sendStr);
return socket_pro.Send(sendBuffer);
}
private string receive()
{
byte[] receiveData = new byte[10240];
int receiveLen = socket_pro.Receive(receiveData);
receiveInfo_pro = encoding_smtp_pro.GetString(receiveData, 0, receiveLen);
Console.WriteLine(receiveInfo_pro);
return receiveInfo_pro;
} #region send ready functions #region isLegal Function
public bool isLegal(string mailHostIP, int port, MailInfo mailInfo)
{
if (!IpPortSp.isPort(port.ToString()))
{
exception_pro = new Exception(Tip.PortIllegal);
return false;
}
if (!MailSp.isMail(mailInfo.senderAddress_pro))
{
exception_pro = new Exception(Tip.SenderIllegal);
return false;
}
return true;
}
#endregion #region isServerReady Function
public bool isServerReady()
{
string back = receive();
return back.Substring(0, 3).Equals(SMTP_BACKS.SERVER_READY_OK);//Response code from server always is 3 byte length.
}
#endregion #region verify Function
public bool verify()
{
socketSend(SMTP_CMD.VERIFY);
string[] verifyBacks = receive().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int index = 0; index < verifyBacks.Length; index++)
{
string verifyBack = verifyBacks[index];
if (verifyBack.Length <= 3)
{
return false;
} if (!verifyBack.Substring(0, 3).Equals(SMTP_BACKS.OPERATE_COMPLETE))
{
return false;
}
}
return true;
}
#endregion #region authLogin function
private bool authLogin()
{
socketSend(SMTP_CMD.AUTH_LOGIN);
string authLoginBack = receive();
if (string.IsNullOrEmpty(authLoginBack) || authLoginBack.Length <= 3)
{
return false;
}
return authLoginBack.Substring(0, 3).Equals(SMTP_BACKS.AUTH_LOGIN_OK);
}
#endregion #region userNameLogin function
private bool userNameLogin(string userName)
{
if (string.IsNullOrEmpty(userName))
{
return false;
}
string base64UserName = Base64Sp.tobase64Str(userName);
socketSend(base64UserName + "\r\n");
string userNameLoginBack = receive();
if (string.IsNullOrEmpty(userNameLoginBack) || userNameLoginBack.Length <= 3)
{
return false;
}
return userNameLoginBack.Substring(0, 3).Equals(SMTP_BACKS.USER_NAME_LOGIN_OK);
} #endregion #region passowrdLogin function
private bool passowrdLogin(string password)
{
if (string.IsNullOrEmpty(password))
{
return false;
}
socketSend(Base64Sp.tobase64Str(password) + "\r\n");
string passowrdLoginBack = receive();
if (string.IsNullOrEmpty(passowrdLoginBack) || passowrdLoginBack.Length <= 3)
{
return false;
}
return passowrdLoginBack.Substring(0, 3).Equals(SMTP_BACKS.PASSWORD_LOGIN_OK);
} #endregion #region mailFrom function
private bool mailFrom(string senderAddress)
{
socketSend(SMTP_CMD.MAIL_FROM + "<" + senderAddress + ">\r\n");
string mailFromBack = receive();
if (string.IsNullOrEmpty(mailFromBack) || mailFromBack.Length <= 3)
{
return false;
}
return mailFromBack.Substring(0, 3).Equals(SMTP_BACKS.OPERATE_COMPLETE);
}
#endregion #region rcptTo function
private bool rcptTo(List<string> receiverAddresses)
{
foreach (string receiverAddress in receiverAddresses)
{
socketSend(SMTP_CMD.RCPT_TO + "<" + receiverAddress + ">\r\n");
string rcptBack = receive();
if (string.IsNullOrEmpty(rcptBack) || rcptBack.Length <= 3)
{
return false;
} if (!rcptBack.Substring(0, 3).Equals(SMTP_BACKS.OPERATE_COMPLETE))
{
return false;
}
}
return true;
}
#endregion #endregion #region send mail body functions
private bool sendMail(MailInfo mailInfo)
{
socketSend(SMTP_CMD.SEND_BODY);
string back = receive();
if (string.IsNullOrEmpty(back) || back.Length <= 3)
{
return false;
} if (!back.Substring(0, 3).Equals(SMTP_BACKS.DATA_OK))
{
return false;
} sendMailHeader(mailInfo);
sendMailContent(mailInfo.content_pro);
sendMailAttachment(mailInfo.attachments_pro);
sendMailTail(); back = receive();
if (string.IsNullOrEmpty(back) || back.Length <= 3)
{
return false;
} if (!back.Substring(0, 3).Equals(SMTP_BACKS.OPERATE_COMPLETE))
{
return false;
} return true;
} private void sendMailAttachment(List<string> attachments)
{
foreach (string attachment in attachments)//Add header per attachment.
{
if (!File.Exists(attachment))
{
continue;
}
sendAttachmentHeader(attachment);
sendAttachmentData(attachment);
}
} private void sendAttachmentData(string attachment)
{
byte[] attachmentData = FileSp.readFileBytes(attachment);
socketSend(Convert.ToBase64String(attachmentData));
socketSend("\r\n\r\n");
} private void sendAttachmentHeader(string attachment)
{
string contentType = "application/octet-stream";//Easy to transmission more format file;
string header = "--" + boundary_pro + "\r\n"
+ "Content-Type:"+contentType+";name=" + attachment + "\r\n"
+ "Content-Transfer-Encoding:base64\r\n"
+ "Content-Disposition:attachment;filename=\"" + attachment + "\"\r\n";
socketSend(header + "\r\n");
} private void sendMailTail()
{
socketSend("\r\n.\r\n");//. is content end flag.
} private void sendMailHeader(MailInfo mailInfo)
{
string to = "";
foreach (string receiverAddress in mailInfo.receiverAddresses_pro)
{
to += "To:" + receiverAddress + "\r\n";
} //if you want to hide receiver,may assign to="To:abc@a.com\r\n";
//string to = "To:abc@a.com\r\n";
socketSend(to); string from = "From:" + mailInfo.senderAddress_pro + "\r\n";
socketSend(from); //Avoid subject messy code,adopt encoding header statement.
string subject = "Subject:=?" + encoding_subject_pro.BodyName + "?B?"
+ Base64Sp.tobase64Str(mailInfo.subject_pro, Encoding.UTF8) + "?=\r\n";
socketSend(subject);
string header = "Mime-Version:1.0\r\n"
+ "Content-type:multipart/mixed;"
+ "boundary=\"" + boundary_pro + "\";\r\n"//define content type and boundary value.
+ "Content-Transfer-Encoding:7bit\r\n"
+ "This is a multi-part message in MIME format\r\n";
socketSend(header + "\r\n");
} private void sendMailContent(string content)
{
sendContentHeader();
sendContentBody(content);
} private void sendContentBody(string content)
{
//If content is too long,need split some blocks and send.
//Length of one line is always 80 byte.
string newContent = Base64Sp.tobase64Str(content, encoding_content_pro);
socketSend(newContent + "\r\n");
} private void sendContentHeader()
{
string header = "--" + boundary_pro + "\r\n"//boundary must begin --
+ "Content-type:text/plain;charset=" + encoding_content_pro.BodyName + "\r\n"//Avoid messy code,add charset statement.
+ "Content-Transfer-Encoding:base64\r\n"//Avoid messy code,use encoding base64.
socketSend(header + "\r\n");
} #endregion private class Tip//Easy to change other language tip.
{
public static string AuthLoginFail = "Auth login fail!";
public static string ConnectFail = "Connect mail host fail!";
public static string IpIllegal = "Ip is illegal!";
public static string MailFromFail = "Input sender address fail!";
public static string PasswordLoginFail = "Password login fail!";
public static string PortIllegal = "Port is illegal!";
public static string ReceiveInfoEmpty = "Receive info is empty!";
public static string RcptToFail = "Input receiver address fail!";
public static string SenderIllegal = "Sender mail address is illegal!";
public static string SendMailFail = "Send mail fail!";
public static string ServerReadyFail = "Server ready fail!";
public static string UserNameLoginFail = "User name login fail!";
public static string VerifyFail = "Verify identity fail!";
}
}
}

具体工程可以到
http://download.csdn.net/detail/xxdddail/5802901下载

C#基于SMTP协议和SOCKET通信,实现邮件内容和附件的发送,并可隐藏收件人的更多相关文章

  1. C语言小项目-基于TCP协议和SOCKET编程的网络通信系统

    1.1 功能结构图   网络通信系统一共由4个模块组成,分别是点对点客户端.点对点服务端.服务器中转服务端.服务器中转客户端.这4个模块是成对使用的,点对点客户端和点对点服务端一起使用,服务器中转服务 ...

  2. TCP协议和socket API 学习笔记

    本文转载至 http://blog.chinaunix.net/uid-16979052-id-3350958.html 分类:  原文地址:TCP协议和socket API 学习笔记 作者:gilb ...

  3. day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信

    day31 recv工作原理 源码解释: Receive up to buffersize bytes from the socket. 接收来自socket缓冲区的字节数据, For the opt ...

  4. TCP/IP协议和socket

    1.传输层基于tcp协议的三次握手和四次挥手? 传输层有两种数据传输协议,分别为TCP协议和UDP协议,其中TCP协议为可靠传输,数据包没有长度设置,理论可以无限长,而UDP协议为不可靠传输,报头一共 ...

  5. 基于多线程的TCP socket通信经典案例

    服务器端 package com.thinkvenus.study.socket; import java.io.BufferedReader; import java.io.IOException; ...

  6. TTMS 一个基于Java Swing的Socket通信的剧院票务管理系统

    TTMS (Theater Ticket Management System) 点我进入github TTMS全称剧院票务管理系统,分为客户端和服务器端.服务器端可以接收客户端连接请求,客户端相当于我 ...

  7. Http TCP/IP协议和socket之间的区别和联系

    总结,TCP/IP是传输层协议,主要解决数据如何在网路中传输,socket是TCP/IP协议的具体实现,是对TCP/IP协议的封装和应用,属于程序员层面,HTTP是应用层协议,应用层协议很多,类似的像 ...

  8. JAVA基础知识之网络编程——-基于AIO的异步Socket通信

    异步IO 下面摘子李刚的<疯狂JAVA讲义> 按照POSIX标准来划分IO,分为同步IO和异步IO.对于IO操作分为两步,1)程序发出IO请求. 2)完成实际的IO操作. 阻塞IO和非阻塞 ...

  9. 关于网络协议和socket编程基本概念

    TCP协议可以说已经是IT人耳熟能详的协议,最近在学习socket网络编程时后重新温习一下这个协议,针对一些问题做了一些总结,很多理解可能还不是很准确. 1. 协议是什么?所谓的各种网络协议无非是一种 ...

随机推荐

  1. order by 字段自动填写脚本

    新版 firefox 中的 hackbar 没有 order by 字段填写, 所以就有了这个: =begin pod sql注入中自动输出order by 的位数 =end pod sub MAIN ...

  2. Visual Studio 2013更新内容简介

    前言 VS2013终于发布了,虽然之前自己使用VS2010和VS2012的时间也不长,尤其是VS2012这自己刚刚也没用多久,看到VS2013发布了,自己忍不住也下载了下来,官网肯定可以下载,不过自己 ...

  3. nginx安装报错:configure: error: the HTTP rewrite module requires the PCRE library

    参考:http://blog.51cto.com/williamx/958398 需要安装pcre-devel与openssl-devel yum -y install pcre-devel open ...

  4. 掩膜 rcnn

    更多讨论,参考知乎:https://www.zhihu.com/question/57403701

  5. java Stack(栈)

    "Stack" 通常时指"后进后出"(LIFO)的容器,有时栈也被称为叠加栈,因为最后"压入"栈的元素,第一个"弹出"栈 ...

  6. 解决Python3 pip list 红色DEPRECATION

    解决Python3 pip list 红色DEPRECATION 打开文件扩展名和隐藏的项目 找到ProgramData,在该目录下创建pip文件夹,在pip里面创建pip.ini  在pip.ini ...

  7. python包管理之Pip安装及使用

    Python有两个著名的包管理工具easy_install.py和pip.在Python2.7的安装包中,easy_install.py是默认安装的,而pip需要我们手动安装. pip可以运行在Uni ...

  8. poj 1611 求0号结点所在集合的元素个数

    求0号结点所在集合的元素个数 Sample Input 100 42 1 25 10 13 11 12 142 0 12 99 2200 21 55 1 2 3 4 51 00 0Sample Out ...

  9. Qt QByteArray或者Char转十六进制 QString

    1.QByteArray转十六进制 QByteArray buff = sp->readAll(); qDebug() << buff.toHex() << " ...

  10. 027.Zabbix的定期备份

    一 数据库备份及恢复 1.1:全库备份 [root@zabbix01 ~]# mysqldump -uroot -p123456 --opt zabbix > zabbix.sql [root@ ...