美文网首页
使用JavaMail向outlook发送会议邀请(日历)邮件

使用JavaMail向outlook发送会议邀请(日历)邮件

作者: 当偶唱起这首歌 | 来源:发表于2019-10-02 20:08 被阅读0次

最近公司招聘系统有一个需求,就是给面试官发送面试邀请邮件的时候,需要发送一个面试提醒,能自动加入到日历中,面试前给面试官提醒,以免忘记。之前没做过发邮件功能,这次网上各种找资料,折腾了好久......

所需依赖:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

Demo:

public class Test1 {
    public static void main(String[] args) {
        sendMeetingInvitationEmail();
    }

    private static Properties props;
    private static Session session;

    public static void sendMeetingInvitationEmail() {
        try {
            props = new Properties();
            //发件人
            String fromEmail = props.getProperty("fromEmail", "XXX@outlook.com");
            //收件人(面试官)
            String toEmail = props.getProperty("toEmail", "XXX@outlook.com");
            props.put("mail.smtp.port", "587");
            props.put("mail.smtp.host", "smtp.office365.com");
            //当前smtp host设为可信任 否则抛出javax.mail.MessagingException: Could not                   convert socket to TLS
            props.put("mail.smtp.ssl.trust", "smtp.office365.com");
            props.put("mail.transport.protocol", "smtp");
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.smtp.ssl", "true");
            //开启debug调试,控制台会打印相关信息
            props.put("mail.debug", "true");
            Authenticator authenticator = new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    //发件人邮箱账号
                    String userId = props.getProperty("userId", "XXX@outlook.com");
                    //发件人邮箱密码(qq、163等邮箱用的是授权码,outlook是密码)
                    String password = props.getProperty("password", "XXXXXXXX");
                    return new PasswordAuthentication(userId, password);
                }
            };
            session = Session.getInstance(props, authenticator);
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(fromEmail));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
            //标题
            message.setSubject("XXX公司诚邀应聘");
            //面试开始时间
            String startTime = getUtc("2019-09-04 14:00");
            //面试结束时间
            String endTime = getUtc("2019-09-04 15:00");
            StringBuffer buffer = new StringBuffer();
            buffer.append("BEGIN:VCALENDAR\n"
                    + "PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN\n"
                    + "VERSION:2.0\n"
                    + "METHOD:REQUEST\n"
                    + "BEGIN:VEVENT\n"
                    //参会者
                    + "ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:你和应聘者\n"
                    //组织者
                    //+ "ORGANIZER:MAILTO:张三\n"
                    + "DTSTART:" + startTime + "\n"
                    + "DTEND:" + endTime + "\n"
                    //面试地点
                    + "LOCATION:会议室01\n"
                    //如果id相同的话,outlook会认为是同一个会议请求,所以使用uuid。
                    + "UID:" + UUID.randomUUID().toString() + "\n"
                    + "CATEGORIES:\n"
                    //会议描述
                    //+ "DESCRIPTION:Stay Hungry.<br>Stay Foolish.\n\n"
                    + "SUMMARY:面试邀请\n" + "PRIORITY:5\n"
                    + "CLASS:PUBLIC\n" + "BEGIN:VALARM\n"
                    //提前10分钟提醒
                    + "TRIGGER:-PT10M\n" + "ACTION:DISPLAY\n"
                    + "DESCRIPTION:Reminder\n" + "END:VALARM\n"
                    + "END:VEVENT\n" + "END:VCALENDAR");
            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setDataHandler(new DataHandler(new ByteArrayDataSource(buffer.toString(),
                    "text/calendar;method=REQUEST;charset=\"UTF-8\"")));
            MimeMultipart multipart = new MimeMultipart();
            MimeBodyPart mimeBodyPart = new MimeBodyPart();
            //String emailText = getHtmlContent(sendEmailApi.getTemplateContent(tempValue),tempMap);
            //文本类型正文
            mimeBodyPart.setText("尊敬的张三:\r您好!\r特邀您...");
            //html类型正文
            //mimeBodyPart.setContent(emailText,"text/html;charset=UTF-8");
            //添加正文
            multipart.addBodyPart(mimeBodyPart);
            //添加日历
            multipart.addBodyPart(messageBodyPart);
            message.setContent(multipart);
            message.setSentDate(new Date());
            message.saveChanges();
            Transport.send(message);
        } catch (MessagingException me) {
            me.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 转utc时间
     *
     * @param str
     * @return
     */
    private static String getUtc(String str) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        long millionSeconds = 0;
        try {
            millionSeconds = sdf.parse(str).getTime();
        } catch (ParseException e1) {
            e1.printStackTrace();
        }
        //utc时间差8小时
        long currentTime = millionSeconds - 8 * 60 * 60 * 1000;
        Date date = new Date(currentTime);
        //格式化日期
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = "";
        nowTime = df.format(date);
        //转换utc时间
        String utcTime = nowTime.replace("-", "").replace(" ", "T").replace(":", "");
        return utcTime;
    }
}

日历功能的话,ical4j也是可以实现的,我这里既然也可实现同样的效果,就偷了个懒。

发送成功的效果:

image

注意事项:

这样的需求虽然不是满大街,但是网上的帖子也不是少的可怜那种,看着就这么点代码,真的折腾了好久,不是报这个错就是报那个错......

  • 发件人邮箱密码:

如果是qq,163等的邮箱,用的是授权码,关于授权码如何获取,请自行百度。如果是outlook邮箱,因为outlook没有什么授权码,用的就是邮箱的登录密码。

  • 服务器地址,端口参数:
props.put("mail.smtp.port", "587");
props.put("mail.smtp.host", "smtp.office365.com");

outlook邮箱如果是个人邮箱,请登录邮箱后设置里面去找(应该都是一样的吧),如下:

outlookSMTP.jpg
outlook邮箱如果不是个人邮箱,是公司邮箱,比如邮箱后缀是@XX公司.com,邮箱服务器地址就是公司的邮箱 服务器地址,端口好像就是常用的25吧。

如果是qq,163邮箱,端口就是25,服务器地址分别为smtp.qq.com、smtp.163.com。其他邮箱的话,抱歉没  有试过。
  • 证书的问题:
javax.mail.MessagingException: Could not convert socket to TLS 
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

不能把socket解析为TLS,不能对访问的目标提供有效证书。

在公司运行的时候,报了这个错。家里用自己outlook账号的话,倒是不会有任何问题...,不用加如下配置,证书也不用导入。

  1. 可以加这个配置,可以把当前邮箱服务器地址设为可信任的。
props.put("mail.smtp.ssl.trust", "smtp.office365.com");//邮箱服务器地址
  1. 另外还可以导入证书

    用工具类生成安全证书或者从浏览器下载证书,放在\JAVA_HOME\jre\lib\security下面

    工具类生成证书:

https://www.tuicool.com/articles/zUjiIb

需要注意的是,帖子里面先javac编译java文件,后执行class文件,执行方式:

Java InstallCert hostname 

hostname 就是发件邮箱的服务器地址,如smtp.office365.com。

浏览器下载证书:

https://blog.csdn.net/frankcheng5143/article/details/52164939

  • 日历参数-参会者:
//参会者
+ "ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:你和应聘者\n"

这个参数我在公司明明是注释的,没有加,可以发送邮件,不知道为什么回到家用自己邮箱发送,不加的话就会报错,一脸懵逼......,现在都还不知道怎么回事。

//无法发送邮件,因为他不包含任何收件人
com.sun.mail.smtp.SMTPSendFailedException: 554 5.2.0 STOREDRV.Submission.Exception:InvalidRecipientsException; Failed to process message due to a permanent exception with message A message can't be sent because it contains no recipients. InvalidRecipientsException: A message can't be sent because it contains no recipients. [Hostname=PS2PR02MB2725.apcprd02.prod.outlook.com]

另外outlook邮箱如果没有绑定手机号(需要验证账户),发送邮件也是会报错的。

  • 身份验证失败:
javax.mail.SendFailedException: Send failure (javax.mail.AuthenticationFailedException: 535 5.7.3 Authentication unsuccessful)

这个问题有点坑人啊,线上环境时不时的发不出邮件,后来一看就是报这个错,邮箱账号密码没错啊......

后来经过排查,发现是这个配置的问题,注释掉就可以了。

props.put("mail.smtp.auth", "true");

这个配置的意思是:是否需要身份验证(默认不验证),公司的邮箱服务器是不需要的,所以注释了也可以发,然后session里面的验证信息也不用传了,不需要账号密码。

session = Session.getInstance(props);

至于为什么设置了需要验证,传了账号密码,有时能发邮件,有时发不出那就不知道了.....这里先记录一下,如果哪位大神知道还望指出。

相关文章

  • 使用JavaMail向outlook发送会议邀请(日历)邮件

    最近公司招聘系统有一个需求,就是给面试官发送面试邀请邮件的时候,需要发送一个面试提醒,能自动加入到日历中,面试前给...

  • 阿里云 - 25端口封禁解决

    使用JavaMail发送邮件在阿里云服务器邮件发送失败 问题发现 问题产生: SpringBoot使用JavaMa...

  • JavaMail

    JavaMail发送邮件工具类 }

  • uipath使用outlook发送邮件

    使用send outlook mail message活动,发送outlook邮件。 to--接收人的邮箱subj...

  • 发送带有附件的 E-mail

    一: 使用JavaMailSender 发送邮件 配置application.yml文件 二.自定义配置JavaMail

  • Javamail发送邮件

    这几篇文章写的就挺好了,传送过去看看吧: 1、 使用JavaMail创建邮件和发送邮件 可能遇到的问题:1、因为端...

  • Javamail发送邮件

    1.添加Maven依赖 2.创建email.properties,设置发邮件邮箱的用户名密码 3.添加EmailA...

  • JavaMail发送邮件

    序:最近谈了个单子,做某Model网站,有发送EDM的需求、爬虫的需求、支付宝…为了帮甲方赶时间,签约之前团队分工...

  • 乐字节-Spring 邮件发送

    Spring 邮件发送 主要内容 JavaMail 概述 ​ JavaMail,顾名思义,提供给开发者处理电子邮件...

  • JSP发送邮件实例

    在本章中,我们将讨论如何使用JSP发送电子邮件。要使用JSP发送电子邮件,应该在计算机上安装JavaMail AP...

网友评论

      本文标题:使用JavaMail向outlook发送会议邀请(日历)邮件

      本文链接:https://www.haomeiwen.com/subject/xfjtyctx.html