前言
公司的邮件系统用的是反人类的 Lotus notes, 你敢信?
最近要实现一个功能,邮件提醒功能,就是通过自动发送提醒邮件
前前后后这个问题搞了2天,由于公司的诸多条件限制,无法直接调用到公司发送邮件的接口,只有通过类似 Lotus script,VBA 等其他方式来实现。
用VBA代码实现发送邮件,其实我在n年前就实现过了
代码如下,网上一搜也一大堆
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
Function SendEmailbyNotesWithAttachement_2(Addresses, Attach, cc) strSubject = ThisWorkbook.Sheets( "EMAIL" ).Range( "B1" ) strbody = ThisWorkbook.Sheets( "EMAIL" ).Range( "A1" ) 'Declare Variables Dim s As Object Dim db As Object Dim body As Object Dim bodyChild As Object Dim header As Object Dim stream As Object Dim host As String Dim message As Object ' Notes variables Set s = CreateObject( "Notes.NotesSession" ) Set db = s.CURRENTDATABASE Set stream = s.CreateStream ' Turn off auto conversion to rtf s.ConvertMIME = False ' Create message Set message = db.CREATEDOCUMENT message.Form = "memo" message.Subject = strSubject message.sendTo = Split(Addresses, ";" ) message.CopyTo = cc message.SaveMessageOnSend = True ' Create the body to hold HTML and attachment Set body = message.CreateMIMEEntity 'Child mime entity which is going to contain the HTML which we put in the stream Set bodyChild = body.CreateChildEntity() Call stream.WriteText(strbody) Call bodyChild.SetContentFromText(stream, "text/HTML;charset=UTF-8" , ENC_NONE) Call stream.Close Call stream.Truncate ' This will run though an array of attachment paths and add them to the email For i = 0 To UBound(Attach) strAttach = Attach(i) If Len(strAttach) > 0 And Len(Dir(strAttach)) > 0 Then ' Get the attachment file name pos = InStrRev(strAttach, "\") Filename = Right(strAttach, Len(strAttach) - pos) 'A new child mime entity to hold a file attachment Set bodyChild = body.CreateChildEntity() Set header = bodyChild.CreateHeader( "Content-Type" ) Call header.SetHeaderVal( "multipart/mixed" ) Set header = bodyChild.CreateHeader( "Content-Disposition" ) Call header.SetHeaderVal( "attachment; filename=" & Filename) Set header = bodyChild.CreateHeader( "Content-ID" ) Call header.SetHeaderVal(Filename) Set stream = s.CreateStream() If Not stream.Open(strAttach, "binary" ) Then MsgBox "Open failed" End If If stream.Bytes = 0 Then MsgBox "File has no content" End If Call bodyChild.SetContentFromBytes(stream, "application/octet-stream" , ENC_IDENTITY_BINARY) ' All my attachments are excel this would need changing depensding on your attachments. End If Next 'Send the email Call message.Send(False) s.ConvertMIME = True ' Restore conversion End Function VBA |
但是现实情况是这样的
我们需要邮件从公邮发送出去
何谓公邮:整个Team使用的邮箱,如***admin@email.com 之类的邮箱
使用过反人类的 Lotus notes 都知道公邮是需要先打开个人邮箱才能进去的
于是当我把以上的VBA 代码增加如下代码,设置从公邮里面发送邮件后
1
2
3
|
Server = "C***/****r/****" Path = "****\C*****.nsf" Set db = s.GetDataBase(Server, Path) |
邮件确实是从公邮发送出来,但是很遗憾,邮件发送人那显示的是我的个人邮箱,而查看我个人的已发送邮件,是完全查不到,但是在公邮已发送邮件可以看到
这就无法理解了,于是开启了漫长的2天人类大战反人类Lotus notes战役
前前后后试过各种VBA代码【表问为什么不直接调接口】
但要不就是能显示为公邮发送的,但邮件 body 不能Html格式,否则就是相反,总之一句话:二者不可兼得
期间看遍国内外关于Lotus notes VBA的网站
最后,实在是忍不了了,开始搜索Python,C#
一直犹犹豫豫没有写是因为同事告诉我,比如使用C#就需要邮箱密码,而这个东西我们没有也不会有的
最后的最后,决定赌一把,我先用C#,直接写出来,等报错提示密码没有的时候我再想办法
于是战战兢兢有了以下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
/// <summary> /// 通过notes发送邮件 /// </summary> /// <param name="mailTo">实时数据库</param> /// <returns></returns> public static void SendForNotes() { string notesPwd = "" ; string notesServer = "C***3/C***/***r/***C" ; string NotesDBName = @"M**l\C***to.nsf" ; string mailTo = "m****o@c**.***.com" ; string mailSubject = DateTime.Now.ToString(); string mailBoby = "<html><body><table border='1'><tr><th>Month</th><th>Savings</th></tr><tr><td>January</td><td>$100</td></tr></table></body></html>" ; NotesSession ns; NotesDatabase db; NotesDocument doc; try { ns = new NotesSession(); if (ns != null ) { //您本机notes的密码 ns.Initialize(notesPwd); //初始化NotesDatabase db = ns.GetDatabase(notesServer, NotesDBName, false ); doc = db.CreateDocument(); doc.ReplaceItemValue( "Form" , "Memo" ); doc.ReplaceItemValue( "SendTo" , mailTo); doc.ReplaceItemValue( "Subject" , mailSubject.Replace( '\r' , ' ' ).Replace( '\n' , ' ' )); doc.AppendItemValue( "Principal" , "C******m" ); //设置邮件的发件人昵称 NotesRichTextItem rt = doc.CreateRichTextItem( "Body" ); var richStyle = ns.CreateRichTextStyle(); richStyle.PassThruHTML = 1; rt.AppendStyle(richStyle); rt.AppendText(mailBoby); //发送邮件 object obj = doc.GetItemValue( "SendTo" ); doc.Send( false , ref obj); doc = null ; } } catch (Exception ex) { // Log.CreateLog(ex.Message); } finally { ns = null ; db = null ; doc = null ; } } |
抱着必死的心态小心翼翼的点击了调试
WTF!!!!
居然收到一封有邮件!没有密码啊!不需要密码吗!密码不用也能发送!!!
再试了一次后,发现真的不需要!!!
因为我们每天开机打开notes的时候也不需要输入密码!!!这可能是和本机的ID文件有绑定!!!在毕业后的第一家公司中是需要输入密码的!
于是欣喜若狂
开始修改代码
最终版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
/// <summary> /// 通过notes发送邮件 /// </summary> /// <param name="mailTo">实时数据库/lysh</param> /// <returns></returns> public static void SendForNotes2() { string notesPwd = "" ; string notesServer = "C****3/**/S***/****" ; string NotesDBName = @"****\******.nsf" ; string mailTo = "****t**@***.com" ; string mailSubject = DateTime.Now.ToString(); string mailBoby = "<html><body><table border='1'><tr><th>Month</th><th>Savings</th></tr><tr><td>January</td><td>$100</td></tr></table></body></html>" ; NotesSession ns; NotesDatabase db; NotesDocument doc; try { ns = new NotesSession(); if (ns != null ) { //您本机notes的密码 ns.Initialize(notesPwd); //初始化NotesDatabase db = ns.GetDatabase(notesServer, NotesDBName, false ); doc = db.CreateDocument(); doc.ReplaceItemValue( "Form" , "Memo" ); doc.ReplaceItemValue( "SendTo" , mailTo); doc.ReplaceItemValue( "Subject" , mailSubject.Replace( '\r' , ' ' ).Replace( '\n' , ' ' )); doc.SaveMessageOnSend = true ; NotesStream HtmlBody = ns.CreateStream(); HtmlBody.WriteText(mailBoby); //构建HTML邮件,可以在头和尾添加公司的logo和系统提醒语 NotesMIMEEntity mine = doc.CreateMIMEEntity( "Body" ); //构建邮件正文 mine.SetContentFromText(HtmlBody, "text/html;charset=UTF-8" , Domino.MIME_ENCODING.ENC_IDENTITY_BINARY); doc.AppendItemValue( "Principal" , "C**********am" ); //设置邮件的发件人昵称 //发送邮件 object obj = doc.GetItemValue( "SendTo" ); doc.Send( false , ref obj); doc = null ; } } catch (Exception ex) { // Log.CreateLog(ex.Message); } finally { ns = null ; db = null ; doc = null ; } } |
期间还遇到
由于这句代码放置的位置不对,导致显示不正确
1
|
doc.AppendItemValue( "Principal" , "C**********am" ); //设置邮件的发件人昵称 |
最终突破的那一刻心情真的很爽,虽然到到现在仍然不知道不要密码的原因,但总归解决了困惑两天的问题,不敢独享
有时候就是听别人说,这条路走不通,就不走了
有时候就是听别人说,已经封装好了,直接调吧,就调了而不知如何实现
有时候就是抄作业,以为自己会了,于是真真用的时候就不知道了
年前终于开始不那么忙了,欠了那么多,该慢慢补回来了
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:http://www.cnblogs.com/LionelMessi/p/8447879.html