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 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