使用 C# 发送 Lotus Notes 电子邮件






4.30/5 (7投票s)
如何使用 C# 发送邮件至 Lotus Notes。
引言
我在工作中遇到了这个问题;我需要通过 Lotus Notes 电子邮件发送一个通知,其中包含错误的描述(ex.Message
)以及导致错误的文件的名称。例如:在数据库中查找 XML 文件中未提供的、用于创建管道分隔的平面文件的值。这会导致平面文件处理失败;它会被移到一个错误文件夹,并创建一个事件日志条目。当然,这对用户没有帮助,但电子邮件可以。互联网上关于 C# 到 Lotus Notes 的信息不多,所以我参考了一些 VBA 示例和一些 C# GUI 示例,并根据我的需要进行了修改,因为现有的方法不适用于 Windows 服务。这样,服务就可以使用应用程序,最重要的是,我只需要查看我的电子邮件即可。
我还使用此过程创建电子邮件,通知另一位用户文件已成功处理,正在等待他们导入 ERP 系统。
背景
此功能的作用
- 在 Windows 服务中自动处理电子邮件流程。
- 在主题行中为用户提供简要描述。例如:账单错误:文件未处理。
- 在电子邮件正文中,它会向用户提供文件名、易于理解的错误信息以及解决问题的有用提示。例如,我们的一些工单没有指定主要技术人员;这个值会在数据库中查找,并且不包含在 XML 文件中。缺少主要技术人员会导致抛出错误(我为此创建了几个自定义异常,例如:
LeadTechNotFoundException
)。我用它来告诉用户去数据库添加主要技术人员,然后将 XML 文件从错误文件夹移回处理文件夹。服务会通过FileSystemWatchers
监视并重新处理它。如果他们复制而不是移动,我会检查文件是否存在并删除它。简单吧?
使用代码
设置对 Domino COM 对象的引用。
此代码可按原样使用或修改。它是完全可用的(至少在我的系统上)。
static void SendNotesErrorMail( string err, string file)
{
//Pass in file name
string filename = file;
//Pass in error message from TryCatch
string errMessage = err;
//Create new notes session
NotesSession _notesSession = new NotesSession();
//Initialize Notes Database to null; nothing in VB.
NotesDatabase _notesDataBase = null;
//Initialize Notes Document to null; nothing in VB.
NotesDocument _notesDocument = null;
//Notes Server Name in form of: ServerName/Domain.
string sServerName = ConfigurationManager.AppSettings [ "ServerName" ];
//Mail File is in form of: mail\\userName.nsf
string sMailFile = ConfigurationManager.AppSettings [ "MailFile" ];
string password = ConfigurationManager.AppSettings [ "Password" ];
string sSendTo = ConfigurationManager.AppSettings [ "SendTo" ];
string sSubject = "Billing Error";
//required for send, since it's byRef and not byVal, gets set later.
object oItemValue = null;
//use string array to CC Send
string[] sCopyTo = new string[4];
sCopyTo [ 0 ] =
ConfigurationManager.AppSettings [ "Recipient0" ];
sCopyTo [ 1 ] =
ConfigurationManager.AppSettings [ "Recipient1" ];
sCopyTo [ 2 ] =
ConfigurationManager.AppSettings [ "Recipient2" ];
sCopyTo [ 3 ] =
ConfigurationManager.AppSettings [ "Recipient3" ];
//Initialize Notes Session
_notesSession.Initialize(password);
//Get Database via server name & c:\notes\data\mailfilename.nsf
//if not found set to false to not create one
_notesDataBase = _notesSession.GetDatabase(sServerName, sMailFile,
false);
//If the database is not already open then open it.
if ( !_notesDataBase.IsOpen )
{
_notesDataBase.Open( );
}
//Create the notes document
_notesDocument = _notesDataBase.CreateDocument();
//Set document type
_notesDocument.ReplaceItemValue(
"Form", "Memo");
//sent notes memo fields (To: CC: Bcc: Subject etc)
_notesDocument.ReplaceItemValue(
"SendTo", sSendTo);
_notesDocument.ReplaceItemValue(
"CopyTo", sCopyTo);
_notesDocument.ReplaceItemValue(
"Subject", sSubject);
//Set the body of the email. This allows you to use the appendtext
NotesRichTextItem _richTextItem = _notesDocument.CreateRichTextItem("Body");
//add lines to memo email body. the \r\n is needed for each new line.
_richTextItem.AppendText(
"Error: " + errMessage + "\r\n");
_richTextItem.AppendText(
"File: " + filename + "\r\n");
_richTextItem.AppendText(
"Resolution: " + resolution + "\r\n");
//send email & pass in byRef field, this case SendTo (always have this,
//cc or bcc may not always be there.
oItemValue = _notesDocument.GetItemValue(
"SendTo" );
_notesDocument.Send(
false, ref oItemValue);
//release resources.
_richTextItem =
null;
_notesDocument =
null;
_notesDataBase =
null;
_notesSession =
null;
}
关注点
这很费劲。有很多关于 VBA / Access / Excel 与 Lotus Notes 的教程等。这里还有一个来自其他用户的相当不错的示例,带有一个 GUI。
我将要做的更改是检查 app.config 文件中的一个值,并根据该计数设置数组大小。我还需要在“分辨率”部分添加一些额外的部分供我的用户使用。如果我有时间,我可能会发布一个示例项目。
这是我在这里的第一个帖子,希望它能帮助到别人。
更新
- 将文件错误写入 sql server 以便跟踪,捕获文件名、日期时间、错误等信息。
- 它为每个文件错误/成功创建并发送一封电子邮件。
- 它将所有电子邮件的副本发送到“主要”电子邮件地址。每条文件错误及其原因,以及发送给客户的每份报告/工单都有记录。
- 我将用于测试的手动流程转换为了一个 Windows 服务,该服务使用目录监视器来捕获放入文件夹的新创建的文件,并按 FIFO(先进先出)的顺序进行处理。
- 我将错误注释掉了,这样您就可以看到哪些是正确的,哪些不是(至少对于我的用途而言)。
- 我使用
Configuration.Manager.AppSettings
变量,因为停止服务、更改一行比编辑代码、重新编译、测试和部署更容易。这样您只需停止服务,更改 app.config 文件,保存然后启动服务。当网络人员更改了您的邮件服务器时,这非常有效。 - 在最后,有一个代码中引用的 App.Config 文件的示例,供那些不知道如何使用它的人参考。
在类的头部分添加 System.net.mail
的 using 语句。
public static void CreateSuccessMessage()
{
string mailServer = ConfigurationManager.AppSettings["ServerName"];
string SendTo = ConfigurationManager.AppSettings["BaanSendTo"];
string SendFrom = ConfigurationManager.AppSettings["SendFrom"];
MailMessage message = new MailMessage(SendFrom, SendTo);
message.Subject = "WorkOrder/Contract Import File Ready.";
message.Body = "File Ready To Process";
SmtpClient client = new SmtpClient(mailServer);
// Credentials are necessary if the server requires the client
// to authenticate before it will send e-mail on the client's behalf.
client.UseDefaultCredentials = false;
client.Send(message);
}
public static void SendSmtpMessage(int messageType, string workContract, string err, string fileName)
{
string mailServer = ConfigurationManager.AppSettings["ServerName"];
string SendFrom = ConfigurationManager.AppSettings["SendFrom"];
MailMessage message = new MailMessage();
if (messageType == 0)
{
//send success message
//string SendTo = ConfigurationManager.AppSettings["BaanSendTo"];
//string CopyTo = ConfigurationManager.AppSettings["Recipient3"];
//message = new MailMessage(SendFrom, SendTo + "," + CopyTo);
//message.Subject = System.Environment.MachineName + ": WorkOrder/Contract Baan Import File Ready.";
//message.Body = fileName + " Is Ready To Process";
//message.Body = "Originating Server: " + System.Environment.MachineName;
//message.Body += System.Environment.NewLine;
}
else
{
//string strSQL = "INSERT INTO tblXmlOutErrors (ErrorDate, ErrorMessage, filename, Server, WorkOrderNumber) " +
// "Values (" + DateTime.Now + ", " + err + ", " + fileName + ", " + System.Environment.MachineName +", " + workContract + ")"; //ContractNumber + ", " + WorkOrderNumber + ")"
string strSQL = "pS1FxXmlOutErrors_Insert ";
strSQL = strSQL + "'" + DateTime.Now + "'," + "'" + err + "'," + "'" + fileName + "'," + "'" + System.Environment.MachineName + "'," + "'" + workContract + "'";
string sqlConnectionString = ConfigurationManager.ConnectionStrings["AppConfigConnectionNameHere"].ConnectionString;
SqlConnection db_conn = new SqlConnection(sqlConnectionString);
SqlCommand ErrorInsertSqlCommand = new SqlCommand();
Trace.WriteLine(strSQL);
ErrorInsertSqlCommand.Connection = db_conn;
ErrorInsertSqlCommand.CommandText = strSQL;
ErrorInsertSqlCommand.CommandType = CommandType.Text;
db_conn.Open();
ErrorInsertSqlCommand.ExecuteNonQuery();
db_conn.Close();
//Send error Message.
string SendTo = ConfigurationManager.AppSettings["SendTo"];
string CopyTo = ConfigurationManager.AppSettings["Recipient1"];
message = new MailMessage(SendFrom, SendTo + "," + CopyTo);
message.Subject = System.Environment.MachineName + ": WorkOrder/Contract File Error.";
message.Body = "Originating Server: " + System.Environment.MachineName;
message.Body += System.Environment.NewLine;
message.Body += "WorkOrder/Contract Number: " + workContract;
message.Body += System.Environment.NewLine;
message.Body += "File That Caused The Error: " + fileName;
message.Body += System.Environment.NewLine;
message.Body += "The Error Message is: " + err;
message.Body += System.Environment.NewLine;
message.Body += "Suggested Action: Go Into System, Correct Values, Save And Re-Export";
}
SmtpClient client = new SmtpClient(mailServer);
// Credentials are necessary if the server requires the client
// to authenticate before it will send e-mail on the client's behalf.
client.UseDefaultCredentials = false;
client.Send(message);
}
public static void SendPdfWorkOrderCompletedEmail(string workContract, string ReportFileName, string strEmailTo, string strMailFrom)
{
string mailServer = ConfigurationManager.AppSettings["ServerName"];
string SendFrom = strMailFrom;
string SendTo = strEmailTo.Replace(";", ",");
SendTo = SendTo + ", hardcodedemainaddresshere";
string recptnts = SendTo.Replace(".com", "");
recptnts = recptnts.Replace(".net", "");
recptnts = recptnts.Replace(".org", "");
recptnts = recptnts.Replace(".biz", "");
MailMessage message = new MailMessage();
message = new MailMessage(SendFrom, SendTo);
message.Subject = "SourceOne Workorder " + workContract + " completed.";
message.Body = "To " + recptnts + ":";
message.Body += System.Environment.NewLine;
message.Body += System.Environment.NewLine;
message.Body += " Your e-mail address(es) are listed on this service event to receive an electronic copy of the Workorder.";
message.Body += System.Environment.NewLine;
message.Body += "The details of this event are included in the attached PDF file.";
message.Body += System.Environment.NewLine;
message.Body += "If you have received this e-mail in error, please reply to have your address removed from future Workorders.";
message.Body += System.Environment.NewLine;
message.Body += "Thank you for your Business.";
message.Body += System.Environment.NewLine;
message.Body += System.Environment.NewLine;
message.Attachments.Add(new Attachment(ReportFileName));
SmtpClient client = new SmtpClient(mailServer);
client.UseDefaultCredentials = false;
client.Send(message);
string strSQL = "StoredProcedureNameToUpdateCustomBoolField_pdfEmailSent ";
strSQL = strSQL + "'" + workContract + "'";
string sqlConnectionString = ConfigurationManager.ConnectionStrings["NameHere"].ConnectionString;
SqlConnection db_conn = new SqlConnection(sqlConnectionString);
SqlCommand PdfSentUpdateSqlCommand = new SqlCommand();
Trace.WriteLine(strSQL);
PdfSentUpdateSqlCommand.Connection = db_conn;
PdfSentUpdateSqlCommand.CommandText = strSQL;
PdfSentUpdateSqlCommand.CommandType = CommandType.Text;
db_conn.Open();
PdfSentUpdateSqlCommand.ExecuteNonQuery();
db_conn.Close();
//if (File.Exists(ReportFileName))
//{
// File.Replace(ReportFileName, ReportFileName,"",true);
// //File.Delete(ReportFileName);
//}
}
public static void SendSmtpBillingFileIssuesMessage()
{
string mailServer = ConfigurationManager.AppSettings["ServerName"];
string SendFrom = ConfigurationManager.AppSettings["SendFrom"];
string SendTo = ConfigurationManager.AppSettings["Recipient5"];
MailMessage message = new MailMessage(SendFrom, SendTo);
message.Subject = "Flat Files To ERP System Building Up.";
message.Body = "Check that the File Transfer Service Is Running, If Not Start It.";
message.Body += System.Environment.NewLine;
message.Body += "Service Runs Every " + ConfigurationManager.AppSettings["ElapsedTime"];
message.Body += System.Environment.NewLine;
message.Body += "Check it again after that time frame, or wait for another mail message.";
SmtpClient client = new SmtpClient(mailServer);
// Credentials are necessary if the server requires the client
// to authenticate before it will send e-mail on the client's behalf.
client.UseDefaultCredentials = false;
client.Send(message);
}
AppConfig 示例:在第一组引号中是代码中的变量 refd
,在第二组引号中是值。
<maillistadd key="FileInPath" value="C:\Folder\subFolder" />
<!-- The File Transfer Timer In Minutes-->
<add key="ElapsedTime" value="5"/>
<add key="ServerName" value="mail.somedomain.com"/>
<add key="SendTo" value="CommaSeperatedInHouseErrorlist"/>
<add key="SendFrom" value="mainemail@somedomain.com"/>
<add key="2nd email SendTo type" value="emaillist"/>
<add key="Recipient0" value="emaillist"/>
<add key="Recipient1" value="maillist"/>
<add key="Recipient2" value="maillist"/>
<add key="Recipient3" value="maillist"/>
<add key="Recipient4" value="maillist"/>
<add key="Recipient5" value="maillist"/>
</appSettings>
<connectionStrings>
<add name="ConnectionVariableName" connectionString="Data Source=ServerName;Initial Catalog=databaseName;Persist Security Info=True;User ID=UserID;Password=PW;MultipleActiveResultSets=True;"/>
</connectionStrings>
就这样。对于发送电子邮件给客户、发送错误到内部部门、发送通知到内部部门以及在数据表中记录错误和问题并进行报告,它都非常好非常好。
希望它有帮助。
祝您愉快!