123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Net.Mail;
- using System.Net.Sockets;
- using System.Text;
- using System.Threading.Tasks;
- namespace BanTur.Core.Utility
- {
- public class MailSender
- {
- private readonly string _host;
- private readonly int _smtpPort;
- private readonly string _user;
- private readonly string _pass;
- private readonly string _senderName;
- public MailSender(string host, int smtpPort, string user, string pass, string senderName)
- {
- _host = host;
- _smtpPort = smtpPort;
- _user = user;
- _pass = pass;
- _senderName = senderName;
- }
- public MailSender() : this(
- DbAccess.Config.SendMailHost,
- DbAccess.Config.SendMailPort,
- DbAccess.Config.SendMailUser,
- DbAccess.Config.SendMailPass,
- "BanTur")
- {
- }
- public void SendMailAndForget(string subject, string body = "")
- {
- Task.Factory.StartNew(() => SendMail(subject, body));
- }
- public void SendMail(string subject, string body = "")
- {
- SendMail(DbAccess.Config.SendMailTarget, subject, DbAccess.Config.SendMailTargetName, body);
- }
- public void SendMail(string to, string subject, string toName, string body)
- {
- var cl = new TcpClient();
- cl.SmtpConnect(_host, _smtpPort);
- cl.SmtpLogin(_user, _pass);
- cl.SmtpSendMail(_user, to, subject, body, _senderName, toName);
- cl.SmtpQuit();
- }
- }
- internal static class MailExtensions
- {
- //-- internal func --
- private static void SmtpCheckStatus(this TcpClient client, int status)
- {
- var line = client.ReadAsciiLine();
- if (line.StartsWith(status + " ") == false)
- throw new SmtpException(line);
- }
- //-- public func --
- public static void SmtpConnect(this TcpClient client, string host, int port)
- {
- client.Connect(host, port);
- client.SmtpCheckStatus(220);
- }
- public static void SmtpLogin(this TcpClient client, string user, string pass)
- {
- client.WriteLine("AUTH LOGIN");
- client.SmtpCheckStatus(334);
- client.WriteLine(Convert.ToBase64String(Encoding.ASCII.GetBytes(user)));
- client.SmtpCheckStatus(334);
- client.WriteLine(Convert.ToBase64String(Encoding.ASCII.GetBytes(pass)));
- client.SmtpCheckStatus(235);
- }
- public static void SmtpSendMail(this TcpClient client, string from, string to, string subject, string body = "", string senderName = "", string toName = "")
- {
- var bodyB64 = Convert.ToBase64String(
- Encoding.UTF8.GetBytes(body + Environment.NewLine + "Mail generate by LibSharpMail")
- , Base64FormattingOptions.InsertLineBreaks);
- client.WriteLine("MAIL FROM: <{0}>", from);
- client.SmtpCheckStatus(250);
- client.WriteLine("RCPT TO: <{0}>", to);
- client.SmtpCheckStatus(250);
- client.WriteLine("DATA");
- client.SmtpCheckStatus(354);
- client.WriteLine("Subject: {0}", subject.SubjectEncoding());
- client.WriteLine("From: \"{1}\" <{0}>", from, senderName.SubjectEncoding());
- client.WriteLine("TO: \"{1}\" <{0}>", to, toName);
- client.WriteLine("MIME-Version: 1.0");
- client.WriteLine("Content-Type: multipart/mixed; boundary=frontier");
- client.WriteLine("");
- client.WriteLine("This is a message with multiple parts in MIME format.");
- client.WriteLine("--frontier");
- client.WriteLine("Content-Type: text/plain; charset=utf-8");
- client.WriteLine("Content-Transfer-Encoding: base64");
- client.WriteLine("");
- client.WriteLine(bodyB64);
- client.WriteLine("--frontier--");
- client.WriteLine(".");
- client.SmtpCheckStatus(250);
- }
- public static void SmtpQuit(this TcpClient client)
- {
- client.WriteLine("QUIT");
- client.SmtpCheckStatus(221);
- client.Close();
- }
- ////////////////////////
- private const byte Cr = (byte)'\r';
- private const byte Lf = (byte)'\n';
- private static readonly byte[] CrLf = { Cr, Lf };
- public static string SubjectEncoding(this string subject, Encoding encoding = null)
- {
- var enc = encoding ?? Encoding.UTF8;
- return $"=?{enc.BodyName}?B?{Convert.ToBase64String(enc.GetBytes(subject))}?=";
- }
- public static void WriteBytes(this Stream s, byte[] bytes)
- {
- s.Write(bytes, 0, bytes.Length);
- }
- public static void WriteCrlf(this Stream s)
- {
- s.WriteBytes(CrLf);
- }
- public static void WriteLine(this TcpClient client, string s)
- {
- client.WriteLine("{0}", s);
- }
- public static void WriteLine(this TcpClient client, string fmt, params object[] args)
- {
- var s = client.GetStream();
- s.WriteBytes(Encoding.ASCII.GetBytes(String.Format(fmt, args)));
- s.WriteCrlf();
- }
- public static byte[] ReadBinLine(this TcpClient client)
- {
- var s = client.GetStream();
- var ms = new MemoryStream();
- var len = 0;
- do
- {
- var b = s.ReadByte();
- if (b < 0)
- continue;
- ms.WriteByte((byte)b);
- len++;
- if (len < 2)
- continue;
- var msbuf = ms.GetBuffer();
- if (msbuf[len - 2] == Cr
- && msbuf[len - 1] == Lf)
- break;
- } while (true);
- var buf = new byte[len - 2];
- Array.Copy(ms.GetBuffer(), 0, buf, 0, len - 2);
- return buf;
- }
- public static string ReadAsciiLine(this TcpClient client)
- {
- return Encoding.ASCII.GetString(client.ReadBinLine());
- }
- public static string[] ReadAsciiLinesUntilDot(this TcpClient client)
- {
- var ret = new List<string>();
- do
- {
- var line = client.ReadAsciiLine();
- if (line.Trim() == ".")
- break;
- ret.Add(line);
- } while (true);
- return ret.ToArray();
- }
- public static byte[][] ReadBinLineUntilDot(this TcpClient client)
- {
- var ret = new List<byte[]>();
- do
- {
- var line = client.ReadBinLine();
- if (line.Length > 0 && line[0] == (byte)'.')
- break;
- ret.Add(line);
- } while (true);
- return ret.ToArray();
- }
- }
- }
|