1. 程式人生 > >javax.mail 處理郵件時由於content-type內容不合標準引起的錯誤

javax.mail 處理郵件時由於content-type內容不合標準引起的錯誤

工作中遇到了使用javax.mail 接收郵件附件時在處理頭資訊中content-type 時報錯的問題,將問題和解決方法記錄下來

一開始使用的是javax.mail 1.4 版本,出現的錯誤程式碼及說明:

這是一段獲的郵件附件的程式碼,在執行for 語句的 multipart.getCount() 方法時報錯

private void unwrapMltipart(Multipart multipart, List<Part> list) throws Exception {  
        // 依次處理各個部分  
        for (int j = 0, n = multipart.getCount(); j < n; j++) {  
            Part part = multipart.getBodyPart(j);
            if (part.getContent() instanceof Multipart) {  
                Multipart p = (Multipart) part.getContent();// 轉成小包裹  
                unwrapMltipart(p, list);  
            } else {  
                String disposition = part.getDisposition();
                if(disposition != null && disposition.equals(Part.ATTACHMENT)){
                    list.add(part);
                }
            }  
        }  
    }

javax.mail.internet.ParseException: Expected '=', got "null"
	at javax.mail.internet.ParameterList.<init>(ParameterList.java:247)
	at javax.mail.internet.ContentType.<init>(ContentType.java:113)
	at javax.mail.internet.MimeMultipart.parsebm(MimeMultipart.java:737)
	at javax.mail.internet.MimeMultipart.parse(MimeMultipart.java:466)
	at javax.mail.internet.MimeMultipart.getCount(MimeMultipart.java:242)

經過程式碼跟蹤發現 

multipart.getCount()  方法在獲取part數量時首先會分析 郵件header裡的Content-Type資訊,裡面包含了郵件格式、boundary等資訊,在boundary之後每多一個資訊需要用;key=value 的格式新增。

而程式報錯時處理的郵件header 的Content-Type 的值卻是這樣的:

Content-Type: multipart/mixed;
 boundary="=_NextPart_2rfkindysadvnqw3nerasdf";gb2312

在讀取完boundary 屬性的值後,把gb2312當成了一個屬性名稱,按照規定後面應該出現 =xxx ,因此報錯。

經過在網上搜索,在 stackoverflow、community.oracle.com  找到類似或相同問題,有位貌似是javax.mail 這段相關程式碼的作者 Bill Shannon的回答非常有幫助。原因是收到的郵件Content-Type 不符合MIME的(RFC 2045, RFC 2046, and RFC 2047)標準造成javax.mail處理時拋異常,可以在使用content-type前修改它以符合標準,他建議應該告訴這封郵件的傳送服務者改到這個錯誤。

解決辦法是使用 javax.mail doc中 Package javax.mail.internet Description 裡介紹的 mail.mime.contenttypehandler 環境變數。
javax.mail 1.4版本還沒有這個變數的功能,我看了1.4.4和1.4.7 版本都有這個功能了。

 這是doc對使用這個環境變數的說明,可以作業系統中新增,或者用System.setProperty("mail.mime.contenttypehandler", "XXX"); 

mail.mime.contenttypehandler                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                String                                                                                                                                                                                                                            In some cases JavaMail is unable to process messages with an invalid Content-Type header. The header may have incorrect syntax or other problems. This property specifies the name of a class that will be used to clean up the Content-Type header value before JavaMail uses it. The class must have a method with this signature: public static String cleanContentType(MimePart mp, String contentType) Whenever JavaMail accesses the Content-Type header of a message, it will pass the value to this method and use the returned value instead. The value may be null if the Content-Type header isn't present. Returning null will cause the default Content-Type to be used. The MimePart may be used to access other headers of the message part to determine how to correct the Content-Type. Note that the Content-Type handler doesn't affect the getHeader method, which still returns the raw header value. Note also that the handler doesn't affect the IMAP provider; the IMAP server is responsible for returning pre-parsed, syntactically correct Content-Type information.

 根據doc介紹的大意我在程式碼中添加了 public static String cleanContentType(MimePart mp, String contentType) 這個方法,這個方法可以處理contentType返回值是經過過濾後的contentType,在實踐中又出現了不能雲行這段方法的問題,需要注意在設定這個mail.mime.contenttypehandler 環境變數時 值是包含cleanContentType方法的類名包含包名也要寫上,javax.mail中的com.sun.mail.util.MimeUtil類是具體負責呼叫這段方法的地方,可以看到其中用反射呼叫這個方法。
在cleanContentType方法對contentType做一下驗證返回一個正確的值,每當javax.mail有地方用到contentType都會經過這個方法。這樣問題就解決。 

相關資訊:

1. MIME標準 http://www.ietf.org/rfc/rfc2045.txt 上可以看到Syntax of the Content-Type Header Field 的說明:

In the Augmented BNF notation of RFC 822, a Content-Type header field
   value is defined as follows:

     content := "Content-Type" ":" type "/" subtype
                *(";" parameter)
                ; Matching of media type and subtype
                ; is ALWAYS case-insensitive.

     type := discrete-type / composite-type

     discrete-type := "text" / "image" / "audio" / "video" /
                      "application" / extension-token

     composite-type := "message" / "multipart" / extension-token

     extension-token := ietf-token / x-token

     ietf-token := <An extension token defined by a
                    standards-track RFC and registered
                    with IANA.>

     x-token := <The two characters "X-" or "x-" followed, with
                 no intervening white space, by any token>

     subtype := extension-token / iana-token

     iana-token := <A publicly-defined extension token. Tokens
                    of this form must be registered with IANA
                    as specified in RFC 2048.>

     parameter := attribute "=" value

     attribute := token
                  ; Matching of attributes
                  ; is ALWAYS case-insensitive.

     value := token / quoted-string

     token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
                 or tspecials>

     tspecials :=  "(" / ")" / "<" / ">" / "@" /
                   "," / ";" / ":" / "\" / <">
                   "/" / "[" / "]" / "?" / "="
                   ; Must be in quoted-string,
                   ; to use within parameter values

2. 網上對這個問題的回答:

https://community.oracle.com/message/9996717#9996717 、 http://stackoverflow.com/questions/18737987/javamail-correct-incoming/18748957

相關推薦

javax.mail 處理郵件由於content-type內容不合標準引起錯誤

工作中遇到了使用javax.mail 接收郵件附件時在處理頭資訊中content-type 時報錯的問題,將問題和解決方法記錄下來 一開始使用的是javax.mail 1.4 版本,出現的錯誤程式碼及說明: 這是一段獲的郵件附件的程式碼,在執行for 語句的 multip

javax.mail 傳送郵件(工具類)

前言:注意自己郵箱賬號的授權碼 傳送不成功,要設定授權碼(勿掉坑裡) 1.座標 <dependency> <groupId>javax.mail</groupId> <artifactId&

Javax.mail 傳送郵件異常

一、執行過程丟擲異常 1、Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream 原因:此異常多出現在J2EE版本的郵件服務中,因為J2EE原

PHP中curl的CURLOPT_POSTFIELDS請求Content-Type多出boundary=------------------------

當我們採用 CURL 在不注意細節的前提下向伺服器傳送一些資料,得到請求頭的CONTENT_TYPE:[CONTENT_TYPE] => multipart/form-data; boundary=—————————-f924413ea122後面多出一個boundary

Java使用javax.mail傳送郵件

這裡使用maven專案進行開發 1.首先pom中載入jar  <dependency>     <groupId>com.sun.mail</groupId>     <artifactId>javax.mail</ar

使用AOP處理註解出現error Type referred to is not an annotation type:xxx

今天本想通過AOP來處理添加註解的介面,結果丟擲了error Type referred to is not an annotation type:xxx(註解名)的異常,原來需要將註解作為處理方法的一個引數傳遞進來,並且引數名字要和@annotation中的名字一樣,不過

Java使用javax.mail傳送郵件 解決收件人、發件人名字亂碼問題

/*** 格式化 Name <[email protected]> 的地址* @param name 名字* @param email Email地址* @return 格式化的地址*/public static String formatAddres

發送get和post請求常用的content-type

encode json數據格式 ima for www 下載 orm 文件上傳 服務器 常見的媒體格式類型如下: text/html : HTML格式 text/plain :純文本格式 text/xml : XML格式

各瀏覽器對常用或者錯誤Content-Type 類型處理方式不一致

mimetype rac apache。 顯示文件 vid ssi 字符 inf 識別 標準參考 content-type 用於定義用戶的瀏覽器或相關設備如何顯示將要加載的數據,或者如何處理將要加載的數據,此屬性的值可以查看 MIME 類型。 MIME (Multipu

使用flask-mail發送電子郵件出現的問題

style windows 出現 ask cat 代理 pan ica 賬號 考慮到gmail設置代理啥的比較麻煩,用幾乎已經不用的163郵箱測試,結果遇到各種問題: 533 authentication is required: 為保證安全性,考慮將賬號和密碼添加進環境變

傳送郵件javax.mail.MessagingException: 501 Syntax: HELO hostname

問題 線上郵件傳送失敗,報異常javax.mail.MessagingException: 501 Syntax: HELO hostname 解決方案 //檢視機器hostname [admin@zyhy-10-1-0-16 ~]$ hostname //檢視host

javax.mail 傳送163郵件

1,匯入maven依賴: <!-- https://mvnrepository.com/artifact/javax.mail/mail --> <dependency> <groupId>javax.mail</groupId>

POSTMAN測試出現 "status": 415, "error": "Unsupported Media Type", "message": "Content type 'app

客戶端使用RESTful呼叫時報status code=415 Unsupported Media Type. 問題產生的原因可能在於客戶端,也可能在於服務端. 使用客戶端做測試時注意設定Headers,以Firefox的外掛RESTClient為例設定如下: 415表示不支援的內

javaMail獲取收件箱郵件javax.mail.FolderNotFoundException

情況一:通過pop3獲取郵件 javax.mail.FolderNotFoundException: folder is not INBOX at com.sun.mail.pop3.POP3Folder.open(POP3Folder.java:205)

關於oozie在發郵件的報錯Caused by: javax.mail.AuthenticationFailedException

今天在做在hue當中,實現oozie的排程然後傳送郵件到郵箱的操作報錯資訊如下:  org.apache.oozie.action.ActionExecutorException: EM007: Encountered an error whi

傳送郵件javax.mail 與 geronimo-javamail_1.4_spec 的jar包衝突

    專案傳送郵件的模組一直使用的是javax.mail 的jar包,後來專案引入了其他的jar多了,然後傳送的郵件全部亂碼了,多方查詢原因發現是javax.mail  和  geronimo-javamail_1.4_spec 的包的路徑是一樣的。專案傳送

java使用javax.mail包傳送電子郵件:設定賬號、密碼、主題、文字、附件

全棧工程師開發手冊 (作者:欒鵬) java使用javax.mail包傳送電子郵件。這個例項可傳送多附件。 這裡使用163郵箱進行測試。可以設定賬號、密碼、主題、文字內容、附件 測試程式碼 public static void mai

javax.mail.AhenticationFailedException: 535 Err / A secure connection is requiered(java發郵件

Java發郵件的幾種方式: JavaMail Commons Email Spring Mail 實驗場景: Spring Mail、Web Project 具體描述: 郵件伺服器: s

Jquery Post提交Content-Type的不同取值詳解

四種常見的 POST 提交資料方式 我們知道,HTTP 協議是以 ASCII 碼傳輸,建立在 TCP/IP 協議之上的應用層規範。規範把 HTTP 請求分為三個部分:狀態行、請求頭、訊息主體。類似於下面這樣: <method> <request-url

javax.mail 呼叫企業郵箱傳送郵件,呼叫個人郵箱傳送郵件

package com; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.BodyPart; import javax.mail.Message; import