📄 inprotocol.java
字号:
* <p> * If the email is plain (not multipart) in such lines are information about * the header of email body. Thats why it is needed to pass body part header * and fill it with information from these lines. * If the email is multipart, we need to extract only body part boundary. * </p> * * @param bpHeader if the email is plain, in content lines are information * about the body of the mail, fill it * @return body part boundary if the email is multipart, * null if the message is plain text * @throws MyException when there is error in getting line from connection * or in decoding */ private String parseContentLines(BodyPart.Header bpHeader) throws MyException { StringBuffer buff = new StringBuffer(); String bodyPartBoundary = null; String line = connection.getLine(); if (DEBUG) System.out.print( "DEBUG InProtocol.parseContentLines(BodyPart.Header) - line: " + line); String lower = line.toLowerCase(); int i; while ( line.charAt(0) == ' ' || line.charAt(0) == '\t' || line.toLowerCase().startsWith("content-") ) { i = lower.indexOf( "boundary=" ); if ( i >= 0 ) { bodyPartBoundary = "--" + getBoundaryParamValue( i, line ); } if (DEBUG) System.out.println("DEBUG InProtocol.parseContentLines(BodyPart.Header) - bodyPartBoundary: " + bodyPartBoundary); i = lower.indexOf("name="); if (i != -1) { bpHeader.setName(Decode.decodeHeaderField(line.substring(i + 5)).trim()); if (bpHeader.getName().charAt(0) == '"') { bpHeader.setName( bpHeader.getName().substring(1, bpHeader.getName().indexOf('"', 2))); } else if (bpHeader.getName().indexOf(';', 1) != -1) { bpHeader.setName( bpHeader.getName().substring(0, bpHeader.getName().indexOf(';', 1)) ); } //let's remove the filename from the string preventing detecting bad charset, //in case the filename itself is named as some charset like windows-1250.txt lower = lower.substring(0, i) + lower.substring(i + 5 + bpHeader.getName().length()); } buff.append(lower); line = connection.getLine(); if (DEBUG) System.out.print( "DEBUG InProtocol.parseContentLines(BodyPart.Header) - line: " + line); lower = line.toLowerCase(); } connection.unGetLine(); //we may be searching in the big String lower, but only once, making it a little faster lower = buff.toString(); if (lower.indexOf("windows-1250") != -1) { bpHeader.setCharSet (BodyPart.CH_WIN1250); } else if (lower.indexOf("iso-8859-1") != -1) { bpHeader.setCharSet( BodyPart.CH_ISO88591 ); } else if (lower.indexOf("iso-8859-2") != -1) { bpHeader.setCharSet( BodyPart.CH_ISO88592 ); } else if (lower.indexOf("utf-8") != -1) { bpHeader.setCharSet( BodyPart.CH_UTF8 ); } if (lower.indexOf("image/") != -1 || lower.indexOf("video/") != -1 || lower.indexOf("audio/") != -1) { bpHeader.setBodyPartContentType( BodyPart.TYPE_MULTIMEDIA ); } else if (lower.indexOf("application/") != -1) { bpHeader.setBodyPartContentType( BodyPart.TYPE_APPLICATION ); } else if (lower.indexOf("text/html") != -1) { bpHeader.setBodyPartContentType( BodyPart.TYPE_HTML ); } else if (lower.indexOf("text/") == -1 && lower.indexOf("content-type") != -1) { bpHeader.setBodyPartContentType( BodyPart.TYPE_OTHER ); } int j = lower.indexOf("content-transfer-encoding:"); if (j != -1) { j += 26; if (lower.indexOf("base64", j) != -1) { bpHeader.setEncoding( BodyPart.ENC_BASE64 ); } else if (lower.indexOf("quoted-printable", j) != -1) { bpHeader.setEncoding( BodyPart.ENC_QUOTEDPRINTABLE ); } else if (lower.indexOf("8bit", j) != -1) { bpHeader.setEncoding( BodyPart.ENC_8BIT ); } } if (DEBUG) System.out.println("DEBUG InProtocol.parseContentLines(BodyPart.Header) - returning bodyPartBoundary: " + bodyPartBoundary); return bodyPartBoundary; } /** * Parses the header of body part in multiparted messages. * If the message is plain, the information about the header of body are * parsed from the lines begining with word content in the header of the * message. See parseContentLines. * @param bpHeader * @return the boundary of the body part header * @throws MyException * @see parseContentLines */ private String parseBodyPartHeader(BodyPart.Header bpHeader) throws MyException { if (DEBUG) { System.out.println("DEBUG InProtocol.parseBodyPartHeader - before execution"); } String line = connection.getLine(); String lower; String bodyPartBoundary = null; while ( ! "\r\n".equals(line) ) { lower = line.toLowerCase(); if (lower.startsWith("content-")) { // return line back, because parseContentLines() needs it connection.unGetLine(); bodyPartBoundary = parseContentLines(bpHeader); } line = connection.getLine(); } return bodyPartBoundary; } /** * Parses and sets charset, types... of header. * * According to MIME, if the message is plain, the information about the body * of such message are in the lines of the message header beginning with * the word content. So such information are parsed during parsing of the * message header. * Thats why when the message is plain, also bodypart is created and added to * the header. See method parseContentLines() for more details. * * @param header the header to be parsed * @throws MyException */ protected void parseHeaders(MessageHeader header) throws MyException { try { String line, lower; //if downloading the whole mail is required then we'll create a BodyPart //because of for a plain (non-mulitpart) mail some information like Charset, MIME encoding are stored in headers lines BodyPart.Header bpHeader = (Settings.downWholeMail && !Settings.safeMode) ? new BodyPart.Header() : null; while (!(line = connection.getLine()).equals("\r\n")) { lower = line.toLowerCase(); if (lower.startsWith("from:")) { header.setFrom(Decode.decodeHeaderField(line.substring(5)).trim()); } else if (lower.startsWith("to:") || lower.startsWith("cc:") || lower.startsWith("bcc:")) { // parse a multiline recipients StringBuffer line2 = new StringBuffer(); do { line2.append(line); line = connection.getLine(); } while (line.startsWith("\t") || line.startsWith(" ")); connection.unGetLine(); String rcps = line2.toString().trim(); if (rcps.length() > 0) { header.addRecipient(Decode.decodeHeaderField(line2.toString()).trim()); } } else if (lower.startsWith("subject:")) { // parse a multiline subject StringBuffer line2 = new StringBuffer(); do { line2.append(line); line = connection.getLine(); } while (line.startsWith("\t") || line.startsWith(" ")); header.setSubject(Decode.decodeHeaderField(line2.toString().substring(8)).trim()); connection.unGetLine(); } else if (lower.startsWith("date:")) { header.setTime(Functions.getStrToLongTime(lower.substring(5))); } else if (lower.startsWith("status:") && line.indexOf("R", 7) != -1) { //this is not defined by rfc, doesnt work on all servers header.markAsRead(); } else if (lower.startsWith("x-status:") && line.indexOf("A", 9) != -1) { //this is not defined by rfc, doesnt work on all servers header.markAsReplied(); } else if (lower.startsWith("content-")) { do { if (lower.indexOf("multipart") != -1) { header.markAsMultipart(); } final int index = lower.indexOf("boundary="); if ( index != -1) { setBoundary( header, index, line, lower ); } // if we for the present don't know whether the mail is multipart // and we want to download whole mail (bp != null -- safer than checking Settings.downloadWholeMail). else if (bpHeader != null) { // if the message is plain, the information about the body are // stored in the header of the message so we need to parse // it and store it to the bpHeader // if the message is multipart, we need only,the boundary // of body parts (and we don't need bpHeader) connection.unGetLine(); String tmpBoundary = parseContentLines(bpHeader); if (DEBUG) System.out.println( "DEBUG parseHeaders(MessageHeader) - " + tmpBoundary ); if (tmpBoundary != null) { //if it has a boundary header.markAsMultipart();// then it must be multipart mail header.setBoundary(tmpBoundary); }//else we have parsed usefull info for nonmutli mail like content transfer, charset.. } line = connection.getLine(); lower = line.toLowerCase(); } while (lower.startsWith(" ") || lower.startsWith("\t")); connection.unGetLine(); } else if ( lower.startsWith( "message-id" ) ) { int startIndex = lower.indexOf("<"); int endIndex = lower.indexOf(">", startIndex); if ( startIndex > -1 ) { final String threadingMessageID = line.substring( startIndex + 1, endIndex ); header.setThreadingMessageID( threadingMessageID ); if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[message-id] - " + threadingMessageID); } } } else if ( lower.startsWith( "in-reply-to" ) ) { int startIndex = lower.indexOf("<"); int endIndex = lower.indexOf(">", startIndex); if ( startIndex > -1 ) { final Vector parentIDs = header.getParentIDs(); if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[in-reply-to] - parentIDs: " + parentIDs); } final String parentID = line.substring( startIndex + 1, endIndex); if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[in-reply-to] - parentID: " + parentID); } header.setParentID( parentID ); if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[in-reply-to] - parentID set"); } if (parentIDs == null) { if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[in-reply-to] - parentIDs vector is null !"); } } } } else if (lower.startsWith("references") ) { int startIndex = lower.indexOf("<"); int endIndex = lower.indexOf(">", startIndex); final Vector/*<String>*/ parentIDs = header.getParentIDs(); if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[references] - parentIDs: " + parentIDs); } String parentID; while ( startIndex > -1) { parentID = line.substring(startIndex + 1, endIndex); if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[references] - parentID: " + parentID); } if ( !parentIDs.contains( parentID ) ) { parentIDs.addElement( parentID ); } startIndex = lower.indexOf("<", endIndex); // when startIndex is -1 end index points to first // occurrence of '>', but it doesn't matter, because // loop ends when startIndex = -1 endIndex = lower.indexOf(">", startIndex); } // while } // if } header.ensureRecipient(account.getEmail()); //if we want to download whole mail (bp != null) and the message is plain // we have already parsed information about body part header from the // message header. So insert the prepared bodypart bp for latter parseBody() call if (bpHeader != null && header.isPlain()) { BodyPart bp = new BodyPart(header, bpHeader); header.addBodyPart(bp); } header.setAccountID(account.getEmail()); header.ensureRecipient(account.getEmail()); //if we want to download whole mail (bp != null) and the message is plain // we have already parsed information about body part header from the // message header. So insert the prepared bodypart bp for latter parseBody() call if (bpHeader != null && header.isPlain()) { BodyPart bp = new BodyPart(header, bpHeader); header.addBodyPart(bp); } header.setAccountID(account.getEmail()); // references field sometimes doesn't contain parentID // (In-Reply-To) field, so we add this one to the references final Vector parentIDs = header.getParentIDs(); final String parentID = header.getParentID(); if ( ! "".equals( parentID ) && ! parentIDs.contains( parentID ) ) { parentIDs.addElement( parentID ); if (DEBUG) { System.out.println("DEBUG InProtocol.parseHeaders(MessageHeader)[in-reply-to] - parentID added to parentIDs vector"); } } // "Message-ID" filed from e-mail header is optional // when it's missing, it's replaced with messageID String threadingMessageID = header.getThreadingMessageID(); if ( threadingMessageID == null || "".equals( threadingMessageID ) ) { header.setThreadingMessageID( header.getMessageID() ); } } catch (RuntimeException re) { if (DEBUG) { System.err.println("ERROR InProtocol.parseHeader() - uncautched exception"); } re.printStackTrace(); throw re; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -