C#操作Lotus Notes邮件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#操作Lotus Notes邮件相关的知识,希望对你有一定的参考价值。

之前的公司一直用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;	
		}
	}

  

 

以上是关于C#操作Lotus Notes邮件的主要内容,如果未能解决你的问题,请参考以下文章

求助Lotus Notes 8.5闪退的问题

使用 Powershell 查找 Lotus Notes 互联网电子邮件地址

Lotus Notes电子邮件作为另一封电子邮件的附件

为啥此电子邮件在 Lotus Notes 中不能正确显示?

lotus domino设置

如何以编程方式将 Lotus Notes 电子邮件文档转换为 MIME 格式