C#基于SMTP协议和SOCKET通信,实现邮件内容和附件的发送,并可隐藏收件人
经过几天的努力,从完全不懂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通信,实现邮件内容和附件的发送,并可隐藏收件人的更多相关文章
- C语言小项目-基于TCP协议和SOCKET编程的网络通信系统
1.1 功能结构图 网络通信系统一共由4个模块组成,分别是点对点客户端.点对点服务端.服务器中转服务端.服务器中转客户端.这4个模块是成对使用的,点对点客户端和点对点服务端一起使用,服务器中转服务 ...
- TCP协议和socket API 学习笔记
本文转载至 http://blog.chinaunix.net/uid-16979052-id-3350958.html 分类: 原文地址:TCP协议和socket API 学习笔记 作者:gilb ...
- day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信
day31 recv工作原理 源码解释: Receive up to buffersize bytes from the socket. 接收来自socket缓冲区的字节数据, For the opt ...
- TCP/IP协议和socket
1.传输层基于tcp协议的三次握手和四次挥手? 传输层有两种数据传输协议,分别为TCP协议和UDP协议,其中TCP协议为可靠传输,数据包没有长度设置,理论可以无限长,而UDP协议为不可靠传输,报头一共 ...
- 基于多线程的TCP socket通信经典案例
服务器端 package com.thinkvenus.study.socket; import java.io.BufferedReader; import java.io.IOException; ...
- TTMS 一个基于Java Swing的Socket通信的剧院票务管理系统
TTMS (Theater Ticket Management System) 点我进入github TTMS全称剧院票务管理系统,分为客户端和服务器端.服务器端可以接收客户端连接请求,客户端相当于我 ...
- Http TCP/IP协议和socket之间的区别和联系
总结,TCP/IP是传输层协议,主要解决数据如何在网路中传输,socket是TCP/IP协议的具体实现,是对TCP/IP协议的封装和应用,属于程序员层面,HTTP是应用层协议,应用层协议很多,类似的像 ...
- JAVA基础知识之网络编程——-基于AIO的异步Socket通信
异步IO 下面摘子李刚的<疯狂JAVA讲义> 按照POSIX标准来划分IO,分为同步IO和异步IO.对于IO操作分为两步,1)程序发出IO请求. 2)完成实际的IO操作. 阻塞IO和非阻塞 ...
- 关于网络协议和socket编程基本概念
TCP协议可以说已经是IT人耳熟能详的协议,最近在学习socket网络编程时后重新温习一下这个协议,针对一些问题做了一些总结,很多理解可能还不是很准确. 1. 协议是什么?所谓的各种网络协议无非是一种 ...
随机推荐
- 第8月第22天 python scrapy
1. cd /Users/temp/Downloads/LagouSpider-master ls ls ls lagou/settings.py cat lagou/settings.py ls p ...
- 爬虫笔记之刷小怪练级:yymp3爬虫(音乐类爬虫)
一.目标 爬取http://www.yymp3.com网站歌曲相关信息,包括歌曲名字.作者相关信息.歌曲的音频数据.歌曲的歌词数据. 二.分析 2.1 歌曲信息.歌曲音频数据下载地址的获取 随便打开一 ...
- MongoDB 之 数据类型 最无聊! But 最有用! MongoDB - 3
MongoDB的新篇章开始啦 - 数据类型 https://www.cnblogs.com/xuzhaocai/p/8048177.html 一.MongoDB 之 丰富多彩的数据类型世界 首先我们要 ...
- G - DNA sequence HDU - 1560
题目链接: https://vjudge.net/contest/254151#problem/G AC代码: #include<iostream> #include<cstring ...
- CEO、COO、CFO、CTO、CXO
CEO:Chief Executive Officer 首席执行官——类似总经理.总裁,是企业的法人代表 COO:Chief Operating Officer 首席营运官——类似常务总经理 CFO: ...
- 串口硬流控原理验证RTS与CTS
物理连接(交叉连接) 主机的RTS(输出)信号,连接到从机的CTS(输入)信号. 主机的CTS(输入)信号,连接到从机的RTS(输出)信号. 主机发送过程: 主机查询主机的CTS脚信号,此信号连接到从 ...
- poj2056
寻找向左凸的地方,每个左凸能让S数量-2.上边或下边如果是半个左凸的话则各对应-1 #include <cstdio> #include <cstring> #include ...
- HTTPS-HTTPS原理
楔子 谣言粉碎机前些日子发布的<用公共WiFi上网会危害银行账户安全吗?>,文中介绍了在使用HTTPS进行网络加密传输的一些情况,从回复来看,争议还是有的.随着网络越来越普及,应用越来越广 ...
- C# Message类的属性Msg所关联的消息ID
C# Message类的属性Msg所关联的消息ID https://msdn.microsoft.com/en-us/library/windows/desktop/ms645606(v=vs.8 ...
- java 异常 throw
throw UnsupportedOperationException(); //没有支持的操作NoSuchElementException(); //没有这样的元素