java發送exchange郵件問題


 最近工作中遇到一個問題,本來很簡單的一個問題,困擾了我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

為什么就可以了呢,很不解,並且這樣的寫法,其他的郵件服務器也是可以用的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM