邮件服务是一般的系统都会拥有和需要的功能,但是对于.NET项目来说,邮件服务的创建和使用会较为的麻烦。.NET对于邮件功能提供了System.Net.Mail用于创建邮件服务,该基础服务提供邮件的基础操作,并且使用也较为的简单。对于真正将该功能使用于项目的人,就会慢慢发现其中的优缺点,甚至有些时候不能忍受其中的问题。在这里介绍一种微软用于替代System.Net.Mail的邮件服务组件MailKit和MimeKit,官网地址:http://www.mimekit.net/。GitHub地址:https://github.com/jstedfast/MimeKit。下面就具体的介绍一下。

  一.MailKit和MimeKit基础概述:

MailKit组件的支持的客户端类型比较多,例如SMTP客户端、POP3客户端、IMAP4客户端。该组件是一个跨平台的Email组件,该组件支持.NET 4.0,.NET 4.5,Xamarin.Android,Xamarin.iOS,Windows Phone 8.1等等平台。

MimeKit提供了一个MIME解析器,组件具备的解析特性灵活、性能高、很好的处理各种各样的破碎的MIME格式化。MimeKit的性能实际上与GMime相当。

该组件在安全性的还是比较高的,处理安全的方式较多,SASL认证、支持S / MIME v3.2、支持OpenPGP、支持DKIM签名等等方式。Mailkit组件可以通过CancellationToken取消对应的操作,CancellationToken传播应取消操作的通知,一个的CancellationToken使线程,线程池工作项目之间,或取消合作任务的对象。过实例化CancellationTokenSource对象来创建取消令牌,该对象管理从其CancellationTokenSource.Token属性检索的取消令牌。然后,将取消令牌传递到应该收到取消通知的任意数量的线程,任务或操作。令牌不能用于启动取消。

MailKit组件支持异步操作,在内部编写的有关I/O异步操作的类。

  二.创建基础邮件服务:

介绍过MailKit和MimeKit组建的基础信息,接下来就介绍一下如何使用两个组件的基本功能,在这里我将基本操作做了一个简单的封装,一般的项目可以直接引用封装好的类,大家可以根据实际的情况对该组件进行扩展。

1.邮件发送基础服务API

    /// <summary>
/// 邮件服务API
/// </summary>
public static class MailServiceApi
{
/// <summary>
/// 发送邮件
/// </summary>
/// <param name="mailBodyEntity">邮件基础信息</param>
/// <param name="sendServerConfiguration">发件人基础信息</param>
public static SendResultEntity SendMail(MailBodyEntity mailBodyEntity,
SendServerConfigurationEntity sendServerConfiguration)
{
if (sendServerConfiguration == null)
{
throw new ArgumentNullException();
} if (sendServerConfiguration == null)
{
throw new ArgumentNullException();
} var sendResultEntity = new SendResultEntity(); using (var client = new SmtpClient(new ProtocolLogger(CreateMailLog())))
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true; Connection(mailBodyEntity, sendServerConfiguration, client, sendResultEntity); if (sendResultEntity.ResultStatus == false)
{
return sendResultEntity;
} SmtpClientBaseMessage(client); Authenticate(mailBodyEntity, sendServerConfiguration, client, sendResultEntity); if (sendResultEntity.ResultStatus == false)
{
return sendResultEntity;
} Send(mailBodyEntity, sendServerConfiguration, client, sendResultEntity); if (sendResultEntity.ResultStatus == false)
{
return sendResultEntity;
} client.Disconnect(true);
} return sendResultEntity;
} /// <summary>
/// 连接服务器
/// </summary>
/// <param name="mailBodyEntity">邮件内容</param>
/// <param name="sendServerConfiguration">发送配置</param>
/// <param name="client">客户端对象</param>
/// <param name="sendResultEntity">发送结果</param>
public static void Connection(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,
SmtpClient client, SendResultEntity sendResultEntity)
{
try
{
client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort);
}
catch (SmtpCommandException ex)
{
sendResultEntity.ResultInformation = $"尝试连接时出错:{0}" + ex.Message;
sendResultEntity.ResultStatus = false;
}
catch (SmtpProtocolException ex)
{
sendResultEntity.ResultInformation = $"尝试连接时的协议错误:{0}" + ex.Message;
sendResultEntity.ResultStatus = false;
}
catch (Exception ex)
{
sendResultEntity.ResultInformation = $"服务器连接错误:{0}" + ex.Message;
sendResultEntity.ResultStatus = false;
}
} /// <summary>
/// 账户认证
/// </summary>
/// <param name="mailBodyEntity">邮件内容</param>
/// <param name="sendServerConfiguration">发送配置</param>
/// <param name="client">客户端对象</param>
/// <param name="sendResultEntity">发送结果</param>
public static void Authenticate(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,
SmtpClient client, SendResultEntity sendResultEntity)
{
try
{
client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);
}
catch (AuthenticationException ex)
{
sendResultEntity.ResultInformation = $"无效的用户名或密码:{0}" + ex.Message;
sendResultEntity.ResultStatus = false;
}
catch (SmtpCommandException ex)
{
sendResultEntity.ResultInformation = $"尝试验证错误:{0}" + ex.Message;
sendResultEntity.ResultStatus = false;
}
catch (SmtpProtocolException ex)
{
sendResultEntity.ResultInformation = $"尝试验证时的协议错误:{0}" + ex.Message;
sendResultEntity.ResultStatus = false;
}
catch (Exception ex)
{
sendResultEntity.ResultInformation = $"账户认证错误:{0}" + ex.Message;
sendResultEntity.ResultStatus = false;
}
} /// <summary>
/// 发送邮件
/// </summary>
/// <param name="mailBodyEntity">邮件内容</param>
/// <param name="sendServerConfiguration">发送配置</param>
/// <param name="client">客户端对象</param>
/// <param name="sendResultEntity">发送结果</param>
public static void Send(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,
SmtpClient client, SendResultEntity sendResultEntity)
{
try
{
client.Send(MailMessage.AssemblyMailMessage(mailBodyEntity));
}
catch (SmtpCommandException ex)
{
switch (ex.ErrorCode)
{
case SmtpErrorCode.RecipientNotAccepted:
sendResultEntity.ResultInformation = $"收件人未被接受:{ex.Message}";
break;
case SmtpErrorCode.SenderNotAccepted:
sendResultEntity.ResultInformation = $"发件人未被接受:{ex.Message}";
break;
case SmtpErrorCode.MessageNotAccepted:
sendResultEntity.ResultInformation = $"消息未被接受:{ex.Message}";
break;
}
sendResultEntity.ResultStatus = false;
}
catch (SmtpProtocolException ex)
{
sendResultEntity.ResultInformation = $"发送消息时的协议错误:{ex.Message}";
sendResultEntity.ResultStatus = false;
}
catch (Exception ex)
{
sendResultEntity.ResultInformation = $"邮件接收失败:{ex.Message}";
sendResultEntity.ResultStatus = false;
}
} /// <summary>
/// 获取SMTP基础信息
/// </summary>
/// <param name="client">客户端对象</param>
/// <returns></returns>
public static MailServerInformation SmtpClientBaseMessage(SmtpClient client)
{
var mailServerInformation = new MailServerInformation
{
Authentication = client.Capabilities.HasFlag(SmtpCapabilities.Authentication),
BinaryMime = client.Capabilities.HasFlag(SmtpCapabilities.BinaryMime),
Dsn = client.Capabilities.HasFlag(SmtpCapabilities.Dsn),
EightBitMime = client.Capabilities.HasFlag(SmtpCapabilities.EightBitMime),
Size = client.MaxSize
}; return mailServerInformation;
} /// <summary>
/// 创建邮件日志文件
/// </summary>
/// <returns></returns>
public static string CreateMailLog()
{
var logPath = AppDomain.CurrentDomain.BaseDirectory + "/DocumentLog/" +
Guid.NewGuid() + ".txt"; if (File.Exists(logPath)) return logPath;
var fs = File.Create(logPath);
fs.Close();
return logPath;
}
}

2.组装邮件消息:

    /// <summary>
/// 邮件信息
/// </summary>
public static class MailMessage
{
/// <summary>
/// 组装邮件文本/附件邮件信息
/// </summary>
/// <param name="mailBodyEntity">邮件消息实体</param>
/// <returns></returns>
public static MimeMessage AssemblyMailMessage(MailBodyEntity mailBodyEntity)
{
if (mailBodyEntity == null)
{
throw new ArgumentNullException(nameof(mailBodyEntity));
} var message = new MimeMessage(); //设置邮件基本信息
SetMailBaseMessage(message, mailBodyEntity); var multipart = new Multipart("mixed"); //插入文本消息
if (string.IsNullOrEmpty(mailBodyEntity.MailTextBody) == false)
{
var alternative = new MultipartAlternative
{
AssemblyMailTextMessage(mailBodyEntity.MailTextBody, mailBodyEntity.MailBodyType)
}; multipart.Add(alternative);
} //插入附件
if (mailBodyEntity.MailFilePath != null && File.Exists(mailBodyEntity.MailFilePath) == false)
{
var mimePart = AssemblyMailAttachmentMessage(mailBodyEntity.MailFileType, mailBodyEntity.MailFileSubType,
mailBodyEntity.MailFilePath); multipart.Add(mimePart);
} //组合邮件内容
message.Body = multipart; return message;
} /// <summary>
/// 设置邮件基础信息
/// </summary>
/// <param name="minMessag"></param>
/// <param name="mailBodyEntity"></param>
/// <returns></returns>
public static MimeMessage SetMailBaseMessage(MimeMessage minMessag, MailBodyEntity mailBodyEntity)
{
if (minMessag == null)
{
throw new ArgumentNullException();
} if (mailBodyEntity == null)
{
throw new ArgumentNullException();
} //插入发件人
minMessag.From.Add(new MailboxAddress(mailBodyEntity.Sender, mailBodyEntity.SenderAddress)); //插入收件人
foreach (var recipients in mailBodyEntity.Recipients)
{
minMessag.To.Add(new MailboxAddress(recipients));
} //插入抄送人
foreach (var cC in mailBodyEntity.Cc)
{
minMessag.Cc.Add(new MailboxAddress(cC));
} //插入主题
minMessag.Subject = mailBodyEntity.Subject; return minMessag;
} /// <summary>
/// 组装邮件文本信息
/// </summary>
/// <param name="mailBody">邮件文本内容</param>
/// <param name="textPartType">邮件文本类型(plain,html,rtf,xml)</param>
/// <returns></returns>
public static TextPart AssemblyMailTextMessage(string mailBody, string textPartType)
{
if (string.IsNullOrEmpty(mailBody))
{
throw new ArgumentNullException();
} if (string.IsNullOrEmpty(textPartType))
{
throw new ArgumentNullException();
} var textBody = new TextPart(textPartType)
{
Text = mailBody
}; return textBody;
} /// <summary>
/// 组装邮件附件信息
/// </summary>
/// <param name="fileAttachmentType">附件类型(image,application)</param>
/// <param name="fileAttachmentSubType">附件子类型 </param>
/// <param name="fileAttachmentPath">附件路径</param>
/// <returns></returns>
public static MimePart AssemblyMailAttachmentMessage(string fileAttachmentType, string fileAttachmentSubType, string fileAttachmentPath)
{
if (string.IsNullOrEmpty(fileAttachmentSubType))
{
throw new ArgumentNullException();
} if (string.IsNullOrEmpty(fileAttachmentType))
{
throw new ArgumentNullException();
} if (string.IsNullOrEmpty(fileAttachmentPath))
{
throw new ArgumentNullException();
} var attachment = new MimePart(fileAttachmentType, fileAttachmentSubType)
{
Content = new MimeContent(File.OpenRead(fileAttachmentPath)),
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Base64,
FileName = Path.GetFileName(fileAttachmentPath)
}; return attachment;
} }

3.邮件基础服务实体:

    /// <summary>
/// 邮件内容实体
/// </summary>
public class MailBodyEntity
{
/// <summary>
/// 邮件文本内容
/// </summary>
public string MailTextBody { get; set; } /// <summary>
/// 邮件内容类型
/// </summary>
public string MailBodyType { get; set; } /// <summary>
/// 邮件附件文件类型
/// </summary>
public string MailFileType { get; set; } /// <summary>
/// 邮件附件文件子类型
/// </summary>
public string MailFileSubType { get; set; } /// <summary>
/// 邮件附件文件路径
/// </summary>
public string MailFilePath { get; set; } /// <summary>
/// 收件人
/// </summary>
public List<string> Recipients { get; set; } /// <summary>
/// 抄送
/// </summary>
public List<string> Cc { get; set; } /// <summary>
/// 发件人
/// </summary>
public string Sender { get; set; } /// <summary>
/// 发件人地址
/// </summary>
public string SenderAddress { get; set; } /// <summary>
/// 邮件主题
/// </summary>
public string Subject { get; set; } /// <summary>
/// 邮件内容
/// </summary>
public string Body { get; set; }
} /// <summary>
/// 邮件服务器基础信息
/// </summary>
public class MailServerInformation
{
/// <summary>
/// SMTP服务器支持SASL机制类型
/// </summary>
public bool Authentication { get; set; } /// <summary>
/// SMTP服务器对消息的大小
/// </summary>
public uint Size { get; set; } /// <summary>
/// SMTP服务器支持传递状态通知
/// </summary>
public bool Dsn { get; set; } /// <summary>
/// SMTP服务器支持Content-Transfer-Encoding
/// </summary>
public bool EightBitMime { get; set; } /// <summary>
/// SMTP服务器支持Content-Transfer-Encoding
/// </summary>
public bool BinaryMime { get; set; } /// <summary>
/// SMTP服务器在消息头中支持UTF-8
/// </summary>
public string UTF8 { get; set; }
} /// <summary>
/// 邮件发送结果
/// </summary>
public class SendResultEntity
{
/// <summary>
/// 结果信息
/// </summary>
public string ResultInformation { get; set; } = "发送成功!"; /// <summary>
/// 结果状态
/// </summary>
public bool ResultStatus { get; set; } = true;
} /// <summary>
/// 邮件发送服务器配置
/// </summary>
public class SendServerConfigurationEntity
{
/// <summary>
/// 邮箱SMTP服务器地址
/// </summary>
public string SmtpHost { get; set; } /// <summary>
/// 邮箱SMTP服务器端口
/// </summary>
public int SmtpPort { get; set; } /// <summary>
/// 是否启用IsSsl
/// </summary>
public bool IsSsl { get; set; } /// <summary>
/// 邮件编码
/// </summary>
public string MailEncoding { get; set; } /// <summary>
/// 发件人账号
/// </summary>
public string SenderAccount { get; set; } /// <summary>
/// 发件人密码
/// </summary>
public string SenderPassword { get; set; } }

上面提供了借助MailKit组建创建发送邮件服务,分别是创建邮件服务器连接,组装邮件基础信息,邮件基础实体。发送邮件的基础服务比较的多,下面介绍一下邮件的接收。

    /// <summary>
/// 跟投邮件服务API
/// </summary>
public static class ReceiveEmailServiceApi
{
/// <summary>
/// 设置发件人信息
/// </summary>
/// <returns></returns>
public static SendServerConfigurationEntity SetSendMessage()
{
var sendServerConfiguration = new SendServerConfigurationEntity
{
SmtpHost = ConfigurationManager.AppSettings["SmtpServer"],
SmtpPort = int.Parse(ConfigurationManager.AppSettings["SmtpPort"]),
IsSsl = Convert.ToBoolean(ConfigurationManager.AppSettings["IsSsl"]),
MailEncoding = ConfigurationManager.AppSettings["MailEncoding"],
SenderAccount = ConfigurationManager.AppSettings["SenderAccount"],
SenderPassword = ConfigurationManager.AppSettings["SenderPassword"]
};
return sendServerConfiguration;
} /// <summary>
/// 接收邮件
/// </summary>
public static void ReceiveEmail()
{
var sendServerConfiguration = SetSendMessage(); if (sendServerConfiguration == null)
{
throw new ArgumentNullException();
} using (var client = new ImapClient(new ProtocolLogger(CreateMailLog())))
{
client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort,
SecureSocketOptions.SslOnConnect);
client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);
client.Inbox.Open(FolderAccess.ReadOnly);
var uids = client.Inbox.Search(SearchQuery.All);
foreach (var uid in uids)
{
var message = client.Inbox.GetMessage(uid);
message.WriteTo($"{uid}.eml");
} client.Disconnect(true);
}
} /// <summary>
/// 下载邮件内容
/// </summary>
public static void DownloadBodyParts()
{
var sendServerConfiguration = SetSendMessage(); using (var client = new ImapClient())
{
client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort,
SecureSocketOptions.SslOnConnect);
client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);
client.Inbox.Open(FolderAccess.ReadOnly); // 搜索Subject标题包含“MimeKit”或“MailKit”的邮件
var query = SearchQuery.SubjectContains("MimeKit").Or(SearchQuery.SubjectContains("MailKit"));
var uids = client.Inbox.Search(query); // 获取搜索结果的摘要信息(我们需要UID和BODYSTRUCTURE每条消息,以便我们可以提取文本正文和附件)
var items = client.Inbox.Fetch(uids, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure); foreach (var item in items)
{
// 确定一个目录来保存内容
var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "/MailBody", item.UniqueId.ToString()); Directory.CreateDirectory(directory); // IMessageSummary.TextBody是一个便利的属性,可以为我们找到“文本/纯文本”的正文部分
var bodyPart = item.TextBody; // 下载'text / plain'正文部分
var body = (TextPart) client.Inbox.GetBodyPart(item.UniqueId, bodyPart); // TextPart.Text是一个便利的属性,它解码内容并将结果转换为我们的字符串
var text = body.Text; File.WriteAllText(Path.Combine(directory, "body.txt"), text); // 现在遍历所有附件并将其保存到磁盘
foreach (var attachment in item.Attachments)
{
// 像我们对内容所做的那样下载附件
var entity = client.Inbox.GetBodyPart(item.UniqueId, attachment); // 附件可以是message / rfc822部件或常规MIME部件
var messagePart = entity as MessagePart;
if (messagePart != null)
{
var rfc822 = messagePart; var path = Path.Combine(directory, attachment.PartSpecifier + ".eml"); rfc822.Message.WriteTo(path);
}
else
{
var part = (MimePart) entity; // 注意:这可能是空的,但大多数会指定一个文件名
var fileName = part.FileName; var path = Path.Combine(directory, fileName); // decode and save the content to a file
using (var stream = File.Create(path))
part.Content.DecodeTo(stream);
}
}
} client.Disconnect(true);
}
} /// <summary>
/// 创建邮件日志文件
/// </summary>
/// <returns></returns>
public static string CreateMailLog()
{
var logPath = AppDomain.CurrentDomain.BaseDirectory + "/DocumentLog/" +
DateTime.Now.ToUniversalTime().ToString(CultureInfo.InvariantCulture) + ".txt"; if (File.Exists(logPath)) return logPath;
var fs = File.Create(logPath);
fs.Close();
return logPath; }
}

上面只是简单的介绍了邮件的接收,如果需要更加深入的了解功能,可以进一步对组件源码进行解析,该组件的文档为较为的丰富。

  三.组件使用感悟:

MailKit和MimeKit组件在项目的使用中较为的便捷,基本包含了所有的基础邮件服务操作。组件提供的SmtpClient类提供的功能很丰富,例如连接邮件服务器,邮件账户认证,组装邮件消息,获取邮件服务器配置信息等等方法的提供,可以让我们在项目中快速的获取邮件服务的所有信息。

使用过邮件功能的项目 都会有困扰,客户端与邮件服务器的连接是否成功,以及邮件是否发送成功状态没有办法很快的获取,只能根据邮件服务器返回的一场状态进行判断。但是MailKit提供对应的方法和异常类,对邮件服务器返回的异常信息进行解析,客户端可以根据这些异常类获取邮件状态。

MailKit组件的提供了ProtocolLogger类,该类用于记录SMTP操作基础信息,该类作用为记录邮件服务日志。在邮件发送完毕后,需要及时的关闭连接,调用Disconnect(true)方法。

创建基于MailKit和MimeKit的.NET基础邮件服务的更多相关文章

  1. MailKit和MimeKit的.NET基础邮件服务

    MailKit和MimeKit的.NET基础邮件服务 邮件服务是一般的系统都会拥有和需要的功能,但是对于.NET项目来说,邮件服务的创建和使用会较为的麻烦..NET对于邮件功能提供了System.Ne ...

  2. 工程师技术(二):postfix基础邮件服务、postfix空客户端邮件服务、搭建mariadb数据库系统、配置一个数据库、使用数据库查询

    一.postfix基础邮件服务 目标: 本例要求在虚拟机server0上配置 postfix 基础服务,具体要求如下: 1> 监听本机的所有接口    2> 将邮件域和邮件服务主机名都改为 ...

  3. 十三.基础邮件服务、parted分区工具、交换分区、链路聚合

    1.基础邮件服务 DNS服务器:虚拟机classroom   以server0.example.com 为例  yg@server0.example.com    xln@server0.exampl ...

  4. postfix基础邮件服务

                                                              postfix基础邮件服务  案例1:postfix基础邮件服务 1.1 问题 本例 ...

  5. MailKit和MimeKit 收发邮件

    新建项目,引用MailKit和MimeKit NuGet包 using CommonTool.MailKit; using System; using System.Collections.Gener ...

  6. 面向服务体系架构(SOA)和数据仓库(DW)的思考基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台

    面向服务体系架构(SOA)和数据仓库(DW)的思考 基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台 当前业界对面向服务体系架构(SOA)和数据仓库(Data Warehouse, ...

  7. 如何基于Winform开发框架或混合框架基础上进行项目的快速开发

    在开发项目的时候,我们为了提高速度和质量,往往不是白手起家,需要基于一定的基础上进行项目的快速开发,这样可以利用整个框架的生态基础模块,以及成熟统一的开发方式,可以极大提高我们开发的效率.本篇随笔就是 ...

  8. 基于RxJava2+Retrofit2精心打造的Android基础框架

    代码地址如下:http://www.demodashi.com/demo/12132.html XSnow 基于RxJava2+Retrofit2精心打造的Android基础框架,包含网络.上传.下载 ...

  9. 创建基于OData的Web API - Knowledge Builder API, Part IV: Write Controller

    基于上一篇<创建基于OData的Web API - Knowledge Builder API, Part III:Write Model and Controller>,新创建的ODat ...

随机推荐

  1. C#基础(六)--枚举的一些常用操作

    本章将介绍以下几点: 1.如何把其它类型转换为枚举类型? 2.如何把枚举中的值添加到下拉菜单中? 一.如何把其它类型转换为枚举类型?        我们回顾一下有关字符串与数字之间的转换,如:     ...

  2. 安装与配置cacti 0.8.8b

    cacti安装与配置 一.安装所需要的软件 Apache    安装Apache文档 Mysql      安装Mysql文档 Php       安装PHP文档 Rrdtool    安装rrdto ...

  3. ctags的使用

    1. 生成tags文件 为当前目录下的所有C程序文件生成对应的tags文件: $ ctags *.c        为同一个目录下的所有文件建立tags如下 $ ctags –R (较常用) 这个命令 ...

  4. Java获得系统的外网IP

    关于如何获得系统外网IP?在网上找了好久,大多数解决方案都没法直接用,所以今天和大家分享一段获得外网IP的代码! import java.net.Inet4Address; import java.n ...

  5. 《Web Scraping With Python》Chapter 2的学习笔记

    You Don't Always Need a Hammer When Michelangelo was asked how he could sculpt a work of art as mast ...

  6. IDEA如何创建及配置Web项目(多图)

    正文之前 在学习Java Web时,第一个遇到的问题就是如何创建或配置Web项目了,今天,就用IntelliJ IDEA 来进行Web项目配置: 创建Web项目 配置web项目 正文 创建Web项目 ...

  7. chrome无法登陆账号,显示操作超时的解决方案

    起因 今天重装了下windows操作系统,准备登陆chrome浏览器,以同步各种插件(你懂的),结果是...无法登陆账号,显示操作超时,真是无语了. 碰到了这个问题第一个直觉是:FQ.突然想到如果修改 ...

  8. Phone文件备份

    一 把照片导入到本地 连接手机和PC,插上数据线后PC上会自动检测并弹出对话框,提示导入 可以指定导入的目录.确定之后点击导入即可开始执行导入操作. 二 把语音备忘录导入到本地 需要借助iTunes联 ...

  9. python学习:猜数字游戏

    猜数字游戏   系统生成一个100以内的随机整数, 玩家有6次机会进行猜猜看,每次猜测都有反馈(猜大了,猜小了,猜对了-结束) 6次中,猜对了,玩家赢了. 否则系统赢了   #!/usr/bin/en ...

  10. 使用IPTABLES限制IP上传下载速度,如何用iptables限速?

    怎样使用IPTABLES限制IP上传下载速度,如何用iptables限速?我们先来看范例: iptables限制某IP的上传速度为1000KB/秒(8Mbps,流入服务器带宽),即在此IP所在的服务器 ...