电子邮件收发
1、课程设计任务与要求
要求能够方便地编辑和发送电子邮件,并将带有附件的邮件发送至用户指定的邮箱(可以多个)。通过学习并掌握System.Net.Mail 命名空间中相关的类(包括Attachment、MailAddress、MailMessage、SmtpClient等)的使用。
并考虑不使用SmtpClient,而是直接使用TCP套接字,编程实现SMTP
的客户端相关功能,最终实现简单邮件的发送。
(1)、深入理解电子邮件系统的构成和SMTP协议的工作原理。
(2)、学习并掌握System.Net.Mail 命名空间中相关的类的使用。
(3)、完成客户发送客户端软件的开发和测试。
2、软件总体设计
电子邮件(简称E-mai1)又称电子信箱、电子邮政是—种用电子手段提供信息交换的通信方式。它是全球多种网络上使用最普遍的一项服务。这种非交互式的通信,加速了信息的交流及数据传送,它是—个简易、快速的方法。通过连接全世界的Internet,实现各类信号的传送、接收、存贮等处理,将邮件送到世界的各个角落。
2.1 软件分析
本设计发送程序采取了既可与发送邮件服务器连接又可以直接与接收邮件服务器连接的方式来实现电子邮件的发送。用户在“收件人邮箱”所对应的对话框中输入收件人的Email地址,并在“发件人邮箱”所对的对话框中输入发信人的Email地址,编辑信件的正文(本例还可以发送附件,只要填写真确的路径,就可以发送附件),然后单击“发送”按钮,便可完成电子邮件的发送。电子邮件发送成功,程序将弹出一个“发送成功”的消息对话框;若电子邮件发送失败,程序将给出失败的相关信息。
2.1.1 SMTP协议简介
SMTP协议是TCP/IP协议族中的一员,主要对如何将电子邮件从发送方地址传送到接收方地址,也即是对传输的规则做了规定。SMTP协议的目标是可靠高效地传送邮件,它独立于传送子系统而且仅要求一条可以保证传送数据单元顺序的通道。SMTP协议通信模型并不复杂,主要工作集中在发送SMTP和接收SMTP上:首先针对用户发出的邮件请求,由
1
发送SMTP建立一条连接到接收SMTP的双工通讯链路,这里的接收SMTP是相对于发送SMTP而言的,实际上它既可以是最终的接收者也可以是中间传送者。发送SMTP负责向接收SMTP发送SMTP命令,而接收SMTP则负责接收并反馈应答。可大致用下面的图1来表示:
图1 SMTP通信模型
2.2 软件设计
本设计是利用Windows应用程序,来实现发送邮件的功能,利用正则表达式验证用户输入的信息,当输入的信息符合要求时,才允许将邮件发送到邮件服务器。
创建一个名为SendMailExample的Windows应用程序,将Form1.cs改名为FormSendMail.cs,设计界面如图2来表示:
图2 发送窗口
2.3 程序设计
2
发送窗口的整体程序设计如下:
using System;
using System.Collections.Generic; using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions; using System.Net;
using System.Net.Mail;
namespace SendMail
{
public partial class FormSendMail : Form
{
public FormSendMail()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//发件人改变时触发
private void textBoxUserName_TextChanged(object sender, EventArgs e)
{
//要求满足电子邮件的格式
BoxUserName.Visible = !Regex.IsMatch(textBoxUserName.Text,
@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
3
}
// 密码改变时触发
private void textBoxPassWord_TextChanged(object sender, EventArgs e)
{
//要求满足5~20个英文字母或者数字的组合
BoxPassWord.Visible = !Regex.IsMatch(textBoxPassWord.Text,
@"^\w{5,20}$");
}
//收件人地址改变时触发
private void textBoxReceive_TextChanged(object sender, EventArgs e)
{
//要求满足电子邮件的格式
BoxReceive.Visible = !Regex.IsMatch(textBoxReceive.Text,
@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
}
//主题改变时触发
private void textBoxSubject_TextChanged(object sender, EventArgs e)
{
//不能为空
BoxSubject.Visible = !Regex.IsMatch(textBoxSubject.Text, @"^.{1,}$");
}
//发送内容改变时触发
private void textBoxBody_TextChanged(object sender, EventArgs e)
{
//不能为空
BoxBody.Visible = !Regex.IsMatch(textBoxUserName.Text, @"^.{1,}$");
}
private void buttonSend_Click(object sender, EventArgs e)
4
{
string invalidString = "";
if (BoxUserName.Visible == true) invalidString += "用户名、";
if (BoxPassWord.Visible == true) invalidString += "口令、";
if (BoxReceive.Visible == true) invalidString += "收件人、";
if (BoxSubject.Visible == true) invalidString += "主题、";
if (BoxBody.Visible == true) invalidString += "邮件内容、";
if (invalidString.Length > 0)
{
MessageBox.Show(invalidString.TrimEnd('、') + "不能为空或者有不符
合规定的内容");
}
else
{
//发件人和收件人的地址
String[] toes = textBoxReceive.Text.Trim().Split(';');
MailAddress from = new MailAddress(textBoxUserName.Text);
MailAddress to = new MailAddress(toes[0]);
MailMessage msg = new MailMessage(from, to);
MailAddressCollection mac = msg.To;
for (Int32 i = 1; i < toes.Length; i++)
{
mac.Add(toes[i]);
}
//邮件主题、内容
MailMessage message = new MailMessage(from, to);
message.Subject = textBoxBody.Text;
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.Body = textBoxBody.Text;
5
message.BodyEncoding = System.Text.Encoding.UTF8;
//添加附件
if (listBox1.Items.Count > 0)
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
Attachment attachFile = new
Attachment(listBox1.Items[i].ToString());
message.Attachments.Add(attachFile);
}
}
try
{
//大部分邮件服务器均加smtp.前缀
SmtpClient client = new SmtpClient("smtp." + from.Host);
SendMail(client, from, textBoxPassWord.Text, to, message);
MessageBox.Show("邮件发送成功");
}
catch (SmtpException err)
{
//如果错误原因是没有找到服务器,则尝试不加smtp.前缀的服务
器
if (err.StatusCode == SmtpStatusCode.GeneralFailure)
{
try
{
//有些邮件服务器不加smtp.前缀
SmtpClient client = new SmtpClient(from.Host);
SendMail(client, from, textBoxPassWord.Text, to,
message);
6
MessageBox.Show("邮件发送成功");
}
catch (SmtpException err1)
{
MessageBox.Show(err1.Message, "发送失败");
}
}
else
{
MessageBox.Show(err.Message, "发送失败");
}
}
}
}
//根据指定的参数发送邮件
private void SendMail(SmtpClient client, MailAddress from, string password,
MailAddress to, MailMessage message)
{
//不使用默认凭证,注意此句必须放在client.Credentials是上面
client.UseDefaultCredentials = false;
//指定用户名、密码
client.Credentials = new NetworkCredential(from.Address, password);
//邮件通过网络发送到服务器
client.DeliveryMethod = SmtpDeliveryMethod.Network;
try
{
client.Send(message);
}
catch
7
{
throw;
}
finally
{
//及时释放占用的资源
message.Dispose();
}
}
private void buttonAdd_Click(object sender, EventArgs e)
{
OpenFileDialog myOpenFileDialog = new OpenFileDialog();
myOpenFileDialog.CheckFileExists = true;
//只接受有效的文件名
myOpenFileDialog.ValidateNames = true;
//允许依次选择多个文件作为附件
myOpenFileDialog.Multiselect = true;
myOpenFileDialog.ShowDialog();
if (myOpenFileDialog.FileName.Length > 0)
{
listBox1.Items.AddRange(myOpenFileDialog.FileNames);
}
}
}
}
2.4程序测试
8
2.4.1 发送邮件中的窗口,如下图3表示:
图3 发送邮件中的窗口
2.4.2 发送邮件成功的窗口,如下图4表示:
图4 发送邮件成功的窗口
3、设计
经过一周的课程设计,感触颇深的是知其然还要知其所以然,不能马马虎虎得过且过,对不会写的代码,要搞明白是什意思,是否自己可以再写一段。此次我们做的设计是最简单的一种,它还存在很多不足,比如系统比较简单,系统的图形操作很缺乏,需要美化,需要人性化,实现的功能也不完善。在输入代码,不得马虎,要不然在运行时就会错误百出,这次课设结合了好几门课程,看来学习不能太孤立,每门课有共同性,有联系,结合起来更容易理解。这就告诉我们学习不能太死板,另外,还要学以致用,光听是学不会的还得自己亲身经历,亲自操作实践,才能领悟。
4、参考文献
[1] Douglas E Comer 著(林瑶译.用TCP/IP进行国际互联 [M](北京:电子工艺出版社,
9
1998:全
[2] Jonathan B Postel著.SMPLEMAL TRANSFER PROTOCOL[S](RFC821,1982:全书
[3]T H H ildebrandt,W L in Optical Recognition of Handritten Chinese Characers:
Pattern Recognition Advances Since,1980,26(2):205~225
课程设计
评 语
课程设计 指导教师
成 绩 (签字) 年 月 日
10
11