之前的公司一直用outlook,朋友的公司在用IBM的Lotus Notes,找我说希望我帮忙做一个基于Notes的邮件提醒功能。但是无法让公司内IT来协助,也就意味着只能在User的电脑上来处理了。
Google了下,有C#的API,并查到在Notes在安装时会在本地配置文件中写入Server Name及基于当前用户的file。好,开干!
首先需要引入Interop.Domino.dll,这个可以去网上找(240K),也可以直接用NuGet搜Domino。
主要写了两个发邮件的Demo方法,一个仿造网上一个Java的Demo转化为C#的写法(逻辑差不多,只是具体的API名称可能不一致),缺点是样式不方便灵活定制。如下:
/// <summary> /// Lotus notes email sender. /// </summary> /// <param name="mail"></param> /// <param name="isSupervisor"></param> static void SendNotesMail(NotesMail mail, bool isSupervisor = false) { try { NotesSession nSession = new NotesSession(); nSession.Initialize(mail.Password); NotesDatabase nDatabase = nSession.GetDatabase(mail.ServerName, mail.FileName); NotesDocument nDocument = nDatabase.CreateDocument(); /*create string variable that will be passed to function. This way we setup To field value*/ //string[] recipients = mail.SendTo; //setup Form nDocument.ReplaceItemValue("Form", "Memo"); nDocument.ReplaceItemValue("SendTo", (object)mail.SendTo); //To field nDocument.ReplaceItemValue("Subject", mail.Subject); //message subject //nDocument.ReplaceItemValue("Body", mail.Body); //set body text NotesRichTextItem richTextItem = nDocument.CreateRichTextItem("Body"); richTextItem.AppendText("Hi,"); richTextItem.AddNewLine(2); if (isSupervisor) { richTextItem.AppendText("The following is completion of today‘s PCN tasks: "); } else { richTextItem.AppendText("The following are the PCN tasks you should comfirm today: "); } richTextItem.AddNewLine(2); // Create table NotesRichTextParagraphStyle rtps = nSession.CreateRichTextParagraphStyle(); rtps.LeftMargin = 0; rtps.FirstLineLeftMargin = 0; rtps.RightMargin = 1; List<NotesRichTextParagraphStyle> styles = new List<NotesRichTextParagraphStyle>(); for (int i = 0; i < 3; i++) { styles.Add(rtps); } var rowNumber = mail.Body.Length; var columnNumber = mail.Body[0].ItemArray.Length; richTextItem.AppendTable(rowNumber, columnNumber); // Populate table NotesRichTextNavigator rtnav = richTextItem.CreateNavigator(); rtnav.FindFirstElement(RT_ELEM.RTELEM_TYPE_TABLECELL); object rtnavo = (object)rtnav; for (int irow = 1; irow <= rowNumber; irow++) { for (int icol = 1; icol <= columnNumber; icol++) { richTextItem.BeginInsert(ref rtnavo); richTextItem.AppendText(mail.Body[irow-1][icol-1].ToString()); richTextItem.EndInsert(); rtnav.FindNextElement(RT_ELEM.RTELEM_TYPE_TABLECELL); } } nDocument.SaveMessageOnSend = mail.SaveMessageOnSend; //save message after it‘s sent object oItemValue = nDocument.GetItemValue("SendTo"); nDocument.Send(false, ref oItemValue); //send } catch (COMException ex) { // Let users change their passwords if their passwords have been changed. The better way is using LDAP to check whether the password is correct or not in a windows service. string logFile = Path.GetFullPath(Path.Combine(logPath, string.Format("{0}.txt", DateTime.Now.ToString("yyyyMMdd")))); if (ex.Message.Contains("Notes error: Wrong Password")) { string SecurityToolPath = ConfigurationManager.AppSettings["ChangePasswordToolPath"]; if (!string.IsNullOrEmpty(SecurityToolPath)&&File.Exists(SecurityToolPath)) { Process.Start(SecurityToolPath); } else { Log(logFile, "Password is wrong but serurity tool can not be found. Please check this config file and find the right path of security tool."); } } Log(logFile, ex.Message + Environment.NewLine + ex.StackTrace); Environment.Exit(0); } catch(Exception ex) { string logFile = Path.GetFullPath(Path.Combine(logPath, string.Format("{0}.txt", DateTime.Now.ToString("yyyyMMdd")))); Log(logFile, ex.Message+Environment.NewLine+ex.StackTrace); Environment.Exit(0); } }
第二种方法可以在邮件中定义比较丰富的内容,因为可以使用HTML格式发送邮件。需要说明的是,我为了简便起见,用Word写了个邮件模板,然后转成HTML格式,再将其分成不同的部分(例如Head,Footer,body,Grid等等)保存在txt文档中,发送邮件时利用这些文件拼成一个HTML文档,如下:
/// <summary> /// Send Notes email using HTML. /// </summary> /// <param name="mail"></param> /// <param name="isSupervisor"></param> static void SendNotesMailWithHTML(NotesMail mail, bool isSupervisor = false) { /* Declare the necessary variables */ NotesSession LNSession = new NotesSession(); NotesDatabase LNDatabase = null; NotesDocument LNDocument; NotesMIMEEntity LNMimeRoot; NotesMIMEEntity LNMime; NotesMIMEHeader LNHeader; NotesStream LNStream; string sMessageBody = string.Empty; try { /* server and username would look similar to the following */ string server = mail.ServerName; string userName = mail.FileName; LNSession.Initialize(mail.Password); /* Since we will be working with MIME entities to create the mail it is important that we turn of the MIME conversion which is turned on by default. */ LNSession.ConvertMime = false; LNDatabase = LNSession.GetDatabase(server, userName, false); /* start creating the mail document: */ LNDocument = LNDatabase.CreateDocument(); LNDocument.SaveMessageOnSend = mail.SaveMessageOnSend; LNDocument.ReplaceItemValue("Form", "Memo"); //LNDocument.ReplaceItemValue("Principal", "System"); /* set the recipients address */ LNDocument.ReplaceItemValue("SendTo", (object)mail.SendTo); /* create the headers */ LNMimeRoot = LNDocument.CreateMIMEEntity(); LNMime = LNMimeRoot.CreateChildEntity(); LNHeader = LNMimeRoot.GetNthHeader("Content-Type"); LNHeader.SetHeaderVal("multipart/related"); /* * Subject is defined twice (in the Subject field and MIME header value) since it is possible that the recipient(s)/client(s) can chose * NOT to display HTML and only show the text part of the mail. * Hence it is preferable set it in both Subject and MIME header. */ LNDocument.ReplaceItemValue("Subject", mail.Subject); LNHeader = LNMime.CreateHeader("Subject"); LNHeader.SetHeaderVal(mail.Subject); LNStream = LNSession.CreateStream(); /* * Build HTML string and attach the HTML body * A sample HTML string is given below * NOTE: Some HTML & CSS styles are not rendered properly in some email clients * RECOMMENDATION: Use basic HTML and Styles */ StringBuilder sb = new StringBuilder(); sb.Append(File.ReadAllText(@"C:\Workbench\Dev\NotesEmailHelper\NotesEmailHelperNet2\HTMLDemo\HTMLHeader.txt")); sb.Append(File.ReadAllText(@"C:\Workbench\Dev\NotesEmailHelper\NotesEmailHelperNet2\HTMLDemo\TableHeader.txt")); if (isSupervisor) { sb.AppendFormat(File.ReadAllText(@"C:\Workbench\Dev\NotesEmailHelper\NotesEmailHelperNet2\HTMLDemo\EmailHeader.txt"), "The following is completion of today‘s PCN tasks: "); } else { sb.AppendFormat(File.ReadAllText(@"C:\Workbench\Dev\NotesEmailHelper\NotesEmailHelperNet2\HTMLDemo\EmailHeader.txt"), "The following are the PCN tasks you should comfirm today: "); } var rowOdd = File.ReadAllText(@"C:\Workbench\Dev\NotesEmailHelper\NotesEmailHelperNet2\HTMLDemo\TableRow1.txt"); var rowEven = File.ReadAllText(@"C:\Workbench\Dev\NotesEmailHelper\NotesEmailHelperNet2\HTMLDemo\TableRow2.txt"); for (int i = 0; i < mail.Body.Length; i++) { if ((i + 1) % 2 == 0) { if (mail.Body[i].ItemArray.Length == 14) { sb.AppendFormat(rowEven, mail.Body[i].ItemArray); } else { continue; } } else { if (mail.Body[i].ItemArray.Length == 14) { sb.AppendFormat(rowOdd, mail.Body[i].ItemArray); } else { continue; } } } sb.Append(File.ReadAllText(@"C:\Workbench\Dev\NotesEmailHelper\NotesEmailHelperNet2\HTMLDemo\HTMLFooter.txt")); sMessageBody = sb.ToString(); /* * The imgage source is given as ‘cid:testmail.png‘ . * It is a marker for the MIME object that it should insert a picture from another MIME object inside the same message. * Therefore we will need to attach the images as well into MIME objects and here comes a really bad thing when attaching files into a Notesdocument: * You must have access to the file system and therefore You need to think about a couple of things: * 1) Is the agent going to be run on the server or locally? * If You run it only locally - then the picture files must reside on the local computer that runs the agent. * If You run it scheduled on a server - then the picture must reside on the servers filesystem. * 2) You must also set the agent security properties to allow restricted operations. */ LNStream.WriteText(sMessageBody); LNMime.SetContentFromText(LNStream, "text/HTML;charset=UTF-8", MIME_ENCODING.ENC_IDENTITY_7BIT); LNStream.Close(); /* attach the image */ //LNMime = LNMimeRoot.CreateChildEntity(); //LNStream.Open(@"<-Give the exact path to your image->"); /* Note that as the second parameter image type needs to be passed as shown below */ //LNMime.SetContentFromBytes(LNStream, "image/png", MIME_ENCODING.ENC_NONE); //LNStream.Close(); //LNMime.EncodeContent(MIME_ENCODING.ENC_BASE64); //LNHeader = LNMime.CreateHeader("Content-ID"); //LNHeader.SetHeaderVal("<- Add here the image source as given in the HTML body. Ex:-testmail.png ->"); /* appending the mail attachment */ //LNMime = LNMimeRoot.CreateChildEntity(); //LNHeader = LNMime.CreateHeader("Content-Disposition"); //LNHeader.SetHeaderValAndParams("attachment; filename=\"<- Enter the file name here ->\""); //LNStream.Open(@"<- Give the exact path to your image ->", "binary"); //LNMime.SetContentFromBytes(LNStream, "application/octet-stream", MIME_ENCODING.ENC_IDENTITY_BINARY); //LNMime.EncodeContent(MIME_ENCODING.ENC_BASE64); //LNStream.Close(); /* send the mail */ LNDocument.Send(false); LNSession.ConvertMime = true; } catch (COMException ex) { string logFile = Path.GetFullPath(Path.Combine(logPath, string.Format("{0}.txt", DateTime.Now.ToString("yyyyMMdd")))); if (ex.Message.Contains("Notes error: Wrong Password")) { string SecurityToolPath = ConfigurationManager.AppSettings["ChangePasswordToolPath"]; if (!string.IsNullOrEmpty(SecurityToolPath)&&File.Exists(SecurityToolPath)) { Process.Start(SecurityToolPath); } else { Log(logFile, "Password is wrong but serurity tool can not be found. Please check this config file and find the right path of security tool."); } } Log(logFile, ex.Message + Environment.NewLine + ex.StackTrace); Environment.Exit(0); } catch(Exception ex) { string logFile = Path.GetFullPath(Path.Combine(logPath, string.Format("{0}.txt", DateTime.Now.ToString("yyyyMMdd")))); Log(logFile, ex.Message+Environment.NewLine+ex.StackTrace); Environment.Exit(0); } finally { /* close all connections */ LNSession = null; LNDatabase = null; LNDocument = null; LNMimeRoot = null; LNMime = null; LNStream = null; LNHeader = null; } }
时间: 2024-10-13 05:03:57