码迷,mamicode.com
首页 > 编程语言 > 详细

java发送exchange邮件问题

时间:2016-08-09 12:11:19      阅读:1068      评论:0      收藏:0      [点我收藏+]

标签:

 最近工作中遇到一个问题,本来很简单的一个问题,困扰了我2周

具体:java发送会议邮件到exchange服务器

奇怪:系统有80多家客户,基本大半都有会议邮件的发送,不管是outlook,网易闪电邮,Foxmail另外wps邮箱都可以接收到会以邮件

只有exchange不能接收到会议邮件,收到的只是

BEGIN:VCALENDAR
PRODID:-//Events Calendar//iCal4j 1.0//EN CALSCALE:GREGORIAN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
DTSTAMP:20160805T115502Z
DTSTART:20160808T160000
DTEND:20160808T223000
SUMMARY:test
LOCATION:test
UID:3f3acf56-0b54-4963-bba2-f02d2c222a8c
ORGANIZER:1
SEQUENCE:0
ATTENDEE;ROLE=OPT-PARTICIPANT;CN=Developer1:mailto:it.test@braccosine.com
 
BEGIN:VALARM
TRIGGER:-PT10M
REPEAT:1
DURATION:PT10M
SUMMARY:Event Alarm
ACTION:DISPLAY
DESCRIPTION:Progress Meeting at 9:30am
END:VALARM
END:VEVENT
END:VCALENDAR

并且邮件中的正文,已附件的形式存在,并且看了网上很多类似的解决方式,综合起来的代码

/**
     * 发送邀请
     * @param cycleModel
     */
    protected void sendEmail(CycleMailModel cycleModel) {
        
        Properties properties = new Properties();
        properties.put("mail.transport.protocol", "smtp");
        properties.put("mail.smtp.user", "smtp.XXX.com");
        properties.put("mail.smtp.host", cycleModel.getEmailHost());
        properties.put("mail.smtp.port", "25");
        properties.put("mail.smtp.auth", "true");

        final String username = cycleModel.getEmailAddress();
        final String password = cycleModel.getEmailPass();
        Authenticator authenticator = new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        };

        Transport transport = null;

        try {
            Session session = Session.getDefaultInstance(properties,
                    authenticator);
            MimeMessage mimeMessage = new MimeMessage(session);
            mimeMessage.setSubject(cycleModel.getSubject());
            if(null != attendee && attendee.size() > 0){
                for (int i = 0; i < attendee.size(); i++) {
                    JSONObject mail = attendee.getJSONObject(i);
                    if(mail.containsKey("address")){
                        mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO,
                                new InternetAddress(mail.getString("address")));
                    }
                }
            }
            mimeMessage.setFrom(new InternetAddress(username));
//method=REQUEST;

            mimeMessage.setSentDate(new Date());
            mimeMessage.setContent(getContentText(cycleModel));
            /*if(cycleModel.getMethodType() == 1){
            }else{
                mimeMessage.setContent(cancelVEvent(cycleModel));
            }*/

            mimeMessage.saveChanges();
            transport = session.getTransport("smtp");
            transport.connect("mail.sfsctech.com",username, password);
            transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
        } catch (MessagingException e) {
            // TODO Auto-generated catch block
            JSONObject exception = JSONObject.fromObject(e);
            //异常邮箱
            if(exception.containsKey("invalidAddresses")){
                JSONArray invalidAddresses = exception.getJSONArray("invalidAddresses");
                if(null != invalidAddresses && invalidAddresses.size() > 0){
                    for (int i = 0; i < invalidAddresses.size(); i++) {
                        //修改发送失败状态
                        JSONObject mailObject = invalidAddresses.getJSONObject(i);
                        this.dao.updateInvalidAddressesState(cycleModel.getPrimaryKey(), mailObject.getString("address"),2,2);
                    }
                    logger.error("异常邮箱:"+invalidAddresses.toString());
                }
            }
            //被退回邮箱
            if(exception.containsKey("validUnsentAddresses")){
                JSONArray validUnsentAddresses = exception.getJSONArray("validUnsentAddresses");
                if(validUnsentAddresses.size() > 0){
                    this.attendee=validUnsentAddresses;
                    sendEmail(cycleModel);
                    System.out.println("会议邮件  发送失败,再次发送");
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (transport != null)
                try {
                    transport.close();
                } catch (MessagingException logOrIgnore) {
                }
        }
    }
    




/**
     * 邀请内容
     * @param cycleModel
     * @return
     * @throws Exception
     */
    protected Multipart getContentText(CycleMailModel cycleModel) throws Exception {
        // 时区
        /*
         * TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance()
         * .createRegistry(); TimeZone timezone =
         * registry.getTimeZone("Asia/Shanghai"); // 会议地点 // 会议时间
         * java.util.Calendar cal = java.util.Calendar.getInstance();
         * 
         * cal.setTimeZone(timezone); cal.set(2015, 6, 2, 14, 0); // 月份是要早一个月
         * DateTime start = new DateTime(cal.getTime()); cal.set(2015, 6, 2, 14,
         * 30); DateTime end = new DateTime(cal.getTime());
         */
        Calendar calendar = new Calendar();
        
        calendar.getProperties().add(
                new ProdId("-//Ben Fortuna//iCal4j 1.0//EN"));
        calendar.getProperties().add(Version.VERSION_2_0);
        calendar.getProperties().add(CalScale.GREGORIAN);
        
        DateTime start = new DateTime(format.parse(cycleModel.getBeginTime().substring(0, 16)).getTime());
        DateTime end = new DateTime(format.parse(cycleModel.getEndTime().substring(0, 16)).getTime());
        VEvent vevent = new VEvent(start, end, cycleModel.getSubject());
        vevent.getProperties().add(new Location(cycleModel.getLocation()));// 会议地点
        vevent.getProperties().add(new Uid(cycleModel.getEventUid()));
        
        Organizer org = new Organizer(URI.create("mailto:" + cycleModel.getEmailAddress()));
        vevent.getProperties().add(org);
        //主键
        Sequence sequence = new Sequence(cycleModel.getSequenceId());
        vevent.getProperties().add(sequence);
        
        
        if(cycleModel.getEventType() == 2){
            String endTime = cycleModel.getBeginTime().substring(0, 10) + " " + cycleModel.getEndTime().substring(11, 16);
            vevent.getEndDate().setDate(new DateTime(format.parse(endTime)));
            //添加事件规则 天、周
            vevent.getProperties().add(getRRule(cycleModel));
        }
        
        // 与会人
        int i = 1;
        for (int j = 0; j < this.attendee.size(); j++) {
            JSONObject emailObject = this.attendee.getJSONObject(j);
            if(emailObject.containsKey("address")){
                Attendee attendee = new Attendee(URI.create("mailto:" + emailObject.getString("address")));
                attendee.getParameters().add(Role.OPT_PARTICIPANT);
                attendee.getParameters().add(new Cn("Developer" + i));
                vevent.getProperties().add(attendee);
                i++;
            }
        }
        
        // --------VEvent Over----------
        // --------VAlarm Start----------
        // 提醒,提前10分钟
        VAlarm valarm = new VAlarm(new Dur(0, 0, -10, 0));
        valarm.getProperties().add(new Repeat(1));
        valarm.getProperties().add(new Duration(new Dur(0, 0, 10, 0)));
        // 提醒窗口显示的文字信息
        valarm.getProperties().add(new Summary("Event Alarm"));
        valarm.getProperties().add(Action.DISPLAY);
        valarm.getProperties().add(
                new Description("Progress Meeting at 9:30am"));
        
        // --------VAlarm Over-------------
        // --------日历对象 Start---------------
        Calendar icsCalendar = new Calendar();
        icsCalendar.getProperties().add(
                new ProdId("-//Events Calendar//iCal4j 1.0//EN"));
        icsCalendar.getProperties().add(CalScale.GREGORIAN);
        icsCalendar.getProperties().add(Version.VERSION_2_0);
        String method = "REQUEST";
        //新增或者编辑
        if(cycleModel.getMethodType().equals(1)){
            vevent.getAlarms().add(valarm);// 将VAlarm加入VEvent
            icsCalendar.getProperties().add(Method.REQUEST);
        }else{
            icsCalendar.getProperties().add(Method.CANCEL);
            method = "CANCEL";
        }
        
        icsCalendar.getComponents().add(vevent);// 将VEvent加入Calendar
        
        icsCalendar.validate();
        
        // 将日历对象转换为二进制流
        CalendarOutputter co = new CalendarOutputter(false);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        co.output(icsCalendar, os);
        byte[] mailbytes = os.toByteArray();
        // --------日历对象 Over------------------
        BodyPart mbp = new MimeBodyPart();
        mbp.setContent(mailbytes, "text/calendar;method="+method+";charset=UTF-8");
        System.out.println("会议邮件  method = "+method);
        
        BodyPart content = new MimeBodyPart();
        content.setContent(cycleModel.getBody(), "text/html;charset=UTF-8");
        System.out.println("会议邮件  Body = "+cycleModel.getBody());
        
        MailcapCommandMap mc = (MailcapCommandMap) CommandMap
                .getDefaultCommandMap();
        mc
                .addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
        mc
                .addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
        mc
                .addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
        mc
                .addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
        mc
                .addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
        CommandMap.setDefaultCommandMap(mc);
        
        MimeMultipart mm = new MimeMultipart();
        mm.setSubType("related");
        mm.addBodyPart(mbp);
        mm.addBodyPart(content);
        return mm;
    }

BodyPart对象不管怎么转码都不能解决问题,并且exchange的服务器设置也没有什么特殊的地方,也没有过滤什么东西,这是为什么呢?

网上找了两种方法:用ical4j和不用

我这里用的就是ical4j,但是不行,不知道其他人是怎么做的

然后我就尝试不用ical4j

protected void sendEmail2(CycleMailModel cycleModel) {

        try {  
            Properties props = new Properties();  
            try {  
                props.put("mail.smtp.port", "25");  
//                props.put("mail.smtp.host", "smtp.xxx.com"); 
                props.put("mail.smtp.host", cycleModel.getEmailHost()); 
                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");  
  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  

            String fromEmail = cycleModel.getEmailAddress();
            String toEmail = this.attendee.getJSONObject(0).getString("address");
            Session session;  

            final String username = cycleModel.getEmailAddress();
            final String password = cycleModel.getEmailPass();
            class EmailAuthenticator extends Authenticator {  
                protected PasswordAuthentication getPasswordAuthentication() {  
                    return new PasswordAuthentication(username, password);  
                }  
            }
            
            Authenticator authenticator = new EmailAuthenticator();  
            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(cycleModel.getSubject());
            StringBuffer buffer = new StringBuffer();
            DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            DateFormat format2 = new SimpleDateFormat("yyyyMMdd:HHmmss");
            String beginTime = format2.format(format1.parse(cycleModel.getBeginTime()));
            beginTime = beginTime.replace(":", "T");
            String endTime = format2.format(format1.parse(cycleModel.getEndTime()));
            endTime = endTime.replace(":", "T");
            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:"+toEmail+"\n"  
                    + "ORGANIZER:MAILTO:"+toEmail+"\n"  
                    + "DTSTART:"  
                    + beginTime+"\n" 
                    + "DTEND:"  
                    + endTime+"\n" 
//                    + "LOCATION:该邮件只是为了在中outlook日历中您请假、外出的情况,无需回复或接受!\n"  
                    + "UID:"+UUID.randomUUID().toString()+"\n"//如果id相同的话,outlook会认为是同一个会议请求,所以使用uuid。  
                    + "CATEGORIES:SuccessCentral Reminder\n"  
                    + "DESCRIPTION:Remind\n\n"  
                    + "SUMMARY:Test meeting request\n" + "PRIORITY:5\n"  
                    + "CLASS:PUBLIC\n" + "BEGIN:VALARM\n"  
                    + "TRIGGER:-PT15M\n" + "ACTION:DISPLAY\n"  
                    + "DESCRIPTION:Reminder\n" + "END:VALARM\n"  
                    + "END:VEVENT\n" + "END:VCALENDAR");  
            BodyPart messageBodyPart = new MimeBodyPart();  
            // 测试下来如果不这么转换的话,会以纯文本的形式发送过去,  
            //如果没有method=REQUEST;charset=\"UTF-8\",outlook会议附件的形式存在,而不是直接打开就是一个会议请求  
            messageBodyPart.setDataHandler(new DataHandler(new ByteArrayDataSource(buffer.toString(),   
                    "text/calendar;method=REQUEST;charset=\"gb2312\"")));  
            System.out.println("邮件:"+buffer.toString());
            Multipart multipart = new MimeMultipart();  
            multipart.addBodyPart(messageBodyPart);  
            message.setContent(multipart);  
            Transport.send(message);  
        } catch (MessagingException me) {  
            // TODO Auto-generated catch block
            JSONObject exception = JSONObject.fromObject(me);
            //异常邮箱
            if(exception.containsKey("invalidAddresses")){
                JSONArray invalidAddresses = exception.getJSONArray("invalidAddresses");
                if(null != invalidAddresses && invalidAddresses.size() > 0){
                    for (int i = 0; i < invalidAddresses.size(); i++) {
                        //修改发送失败状态
                        JSONObject mailObject = invalidAddresses.getJSONObject(i);
                        this.dao.updateInvalidAddressesState(cycleModel.getPrimaryKey(), mailObject.getString("address"),2,2);
                    }
                    logger.error("异常邮箱:"+invalidAddresses.toString());
                }
            }
            //被退回邮箱
            if(exception.containsKey("validUnsentAddresses")){
                JSONArray validUnsentAddresses = exception.getJSONArray("validUnsentAddresses");
                if(validUnsentAddresses.size() > 0){
                    this.attendee=validUnsentAddresses;
                    sendEmail2(cycleModel);
                    System.out.println("会议邮件  发送失败,再次发送");
                }
            }
            me.printStackTrace();  
        } catch (Exception ex) {  
            ex.printStackTrace();  
        }  
    }

这样做了,竟然就可以接收到了,我很无语

 

仔细看代码,没有ical4j的日历对象,也没有把邮件的正文或者日历对象转成  text/html;charset=UTF-8

为什么就可以了呢,很不解,并且这样的写法,其他的邮件服务器也是可以用的

java发送exchange邮件问题

标签:

原文地址:http://www.cnblogs.com/wy3427/p/5752604.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!