VBA 中发送邮件(三. 使用 XMLHttpRequest 组件)

w3 JMail 组件虽好用,但实际使用过程中还是碰到问题,多数机器上都表现正常,唯独在一台机器上,JMail 的错误信息总是:jmail The message was undeliverable. All servers failed to receive the message。根据经验把病毒软件、防火墙都关了,Telnet 到邮件服务器的 25 端口,或者 Outlook 收发都是正常的,这下有些没辙了,而同事真正又要在那台奇怪的机器上发邮件。

再想它法了,对,就是 XMLHttpRequest,把功能分离,Excel 只提交 Http 请求,由 JSP 来完成实际的邮件发送工作,当然也可以实现为其他的形式。所以也就有两部分实现代码,分别为:

JSP 代码,使用的是 Apache 的 commons-email 组件,它还需要用到 activation.jar 和 mail.jar, 关于 commons-email 的使用可参考前面的一篇: 用 apache commons-email 轻松发送无乱码邮件。 比如文件存为 sendmail.jsp,通过浏览器来访问时用的 URL 是 http://192.168.1.100:8080/WebUtils/sendmail.jsp
 1<%@ page contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>
 2<%@ page import="org.apache.commons.mail.*,java.net.*"%>
 3<%
 4
 5/*发送邮件的页面,只允许以 post 方式提交
 6  参数说明:
 7  to: 邮件接收人
 8  subject: 邮件标题
 9  body:   邮件正文
10*/
11
12String method = request.getMethod();
13
14if(method.equalsIgnoreCase("post")){ //只处理 post 请求
15
16     //把请求的字符集设为 iso8859-1,然后调用 toUTF8 来解决乱码问题
17     request.setCharacterEncoding("iso8859-1");
18     String to = toUTF8(request.getParameter("to"));
19     String subject = toUTF8(request.getParameter("subject"));
20     String body = toUTF8(request.getParameter("body"));
21
22     // 发送带附件及HTML内容的邮件
23     HtmlEmail email = new HtmlEmail();
24     email.setHostName("smtp.sina.com");
25
26     // 需要邮件发送服务器验证,用户名/密码
27     email.setAuthentication("fantasia", "xxxxxx");
28     email.addTo(to);
29     email.setFrom("fantasia@sina.com", "Unmi");
30
31     // 设置主题的字符集为UTF-8
32     email.setCharset("UTF-8");
33     email.setSubject(subject);
34     try{
35         email.setHtmlMsg(body);
36         email.attach(new URL("file:///c|SendMail.java"), "SendMail.java","SendMail.java");
37         email.buildMimeMessage();
38         email.send();
39         out.print("发送成功");
40     }catch(Exception ex){
41         out.print(ex.getMessage());
42     }
43}
44%>
45
46<%!
47    private String toUTF8(String src) throws UnsupportedEncodingException{
48        String dst = new String(src.getBytes("ISO8859-1"),"UTF-8");
49        return dst;
50    }
51%>

VBA 代码,在它的 Visual Basic 的编辑器中需要引用 Microsoft XML, v6.0 (或者其他相应版本,如 v2.6、v3.0、v4.0、v5.0):
 1Function SendEmailByHttp(MailTo, Subject, Body)
 2    Dim XmlHttp As New MSXML2.XMLHTTP60 '变量类型视你引用的 MSXML 版本略有不同,如 XMLHTTP50
 3    Dim PageUrl, data
 4    data = "to=" & MailTo & "subject=" & Subject & "&body=" & Body
 5    PageUrl = "http://192.168.1.100:8080/WebUtils/sendmail.jsp"
 6
 7    '假如你的 web 应用配置了诸如 form 验证,则需加上后两个参数
 8    XmlHttp.Open "POST", PageUrl, False, "username", "password" '同步方式
 9
10    'post 提交 form 时需要设置这个请求头
11    XmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
12
13    '后面几行有关于设置请求头中的字符集好像解决不了乱码问题
14    'XmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"
15    'XmlHttp.setRequestHeader "Accept-Charset", "UTF-8"
16    'XmlHttp.setRequestHeader "charset", "UTF-8"
17    'XmlHttp.setRequestHeader "Content-Type", "charset=UTF-8"
18
19    XmlHttp.Send data '发送请求
20    If XmlHttp.Status = 200 Then
21
22        '去除 jsp 中输出的回车、换行和两边空格
23        SendEmailByHttp = Trim(Replace(Replace(XmlHttp.responseText, Chr(10), ""), Chr(13), ""))
24    Else
25        SendEmailByHttp = "发送失败!" '请求不正常的失败返回
26    End If
27End Function

可以在你的 Excel 表格中加个按钮,一点击按钮,程序循环的取表格中的数据,如参数 MailTo、Subject、Body 由 Excel 来提供。有关于 Excel 表格数据的读取这里就不涉及了。

参考:1. XmlHttpRequest的Post请求方式示例
        2. Using XmlHttp Correctly
        3. The XMLHttpRequest Object

永久链接 https://yanbin.blog/vba-send-email-xmlhttprequest/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。