mailmessage.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 1,042 行 · 第 1/3 页

CPP
1,042
字号
 *
 * @param rfcBody  (in)  - message content
 * @param boundary (in)  - mime boundary string
 * @param ret      (out) - parsed BodyPart
 * @param next     (i/o) - offset of the new boundary
 * @param isAttach (in)  - says if the current body part is an attachment or not
 */
static bool getBodyPart(StringBuffer &rfcBody, StringBuffer &boundary,
                       BodyPart &ret, size_t &next, bool isAttach)
{
    LOG.debug("getBodyPart START");
    StringBuffer newline;

    // The part starts on the next line
    size_t begin = findNewLine(rfcBody, next);
    if (begin == StringBuffer::npos)
       return false;
    // find the end of the part
    next = rfcBody.find(boundary, begin);
    if (next == StringBuffer::npos)
       return false;
    // get the part
    StringBuffer part = rfcBody.substr(begin, next-begin);
    // If it is a multipart alternative part, get the text part only.
    // check only until the first new line not on all the message (it could be
    // a message inside another message)
    size_t headers_len = getHeadersLen(part, newline);
    StringBuffer headers_part = part.substr(0, headers_len);
    if (headers_part.ifind("Content-Type: multipart/alternative") != StringBuffer::npos) {
        if(part.ifind("Content-Type: multipart/alternative") != StringBuffer::npos) {
            size_t b_pos = part.ifind("boundary=");
            if( b_pos != StringBuffer::npos ) {
                size_t begin = part.find("=\"", b_pos) + 2 ;
                size_t end = part.find("\"", begin) ;

                StringBuffer inner_boundary("\n--");
                inner_boundary += part.substr( begin, end-begin );

                begin = part.find(inner_boundary, end);
                begin += inner_boundary.length();
                end = part.find(inner_boundary, begin);
                if (begin != StringBuffer::npos && end != StringBuffer::npos) {
                    part = part.substr(begin, end-begin);
                    LOG.debug("Bodypart is multipart/alternative: "
                        "getting first alternative only: \n%s\n", part.c_str() );
                }
            }
        }
    }

    // Split headers and body
    size_t hdrlen = getHeadersLen(part, newline);

    // Get headers
    StringBuffer headers = part.substr(0, hdrlen);

    // Join header parts using \t or 8 blank
    StringBuffer joinlinetab("\t");
    headers.replaceAll(joinlinetab, " ");
    StringBuffer joinlinespaces(newline);
    joinlinespaces+=" ";  // 8 blanks
    headers.replaceAll(joinlinespaces, " ");

    ArrayList lines;
    const StringBuffer *line;

    // parse the bodypart headers
    headers.split(lines, newline);

    for ( line=(StringBuffer *)lines.front();
          line;
          line=(StringBuffer *)lines.next() ) {
        if( *line == "\r" )
            continue;
        // The first empty line marks the end of the header section
        //if( line->empty() ){
        //    break;
        //}
        // Process the headers
        if( line->ifind(MIMETYPE) == 0 ) {  // it must at the beginning
            ret.setMimeType(getTokenValue(line, MIMETYPE));
            if (line->ifind(CT_NAME) != StringBuffer::npos) {
                ret.setName(MailMessage::decodeHeader(getTokenValue(line, CT_NAME,false)));
            }
            if (line->ifind(CT_CHARSET) != StringBuffer::npos ) {
                ret.setCharset(getTokenValue(line, CT_CHARSET));
            }
        }   
        else if( line->ifind(DISPOSITION) == 0 ) {
            ret.setDisposition( getTokenValue(line, DISPOSITION));
            if (line->ifind(CD_FILENAME) != StringBuffer::npos ) {
                ret.setFilename( MailMessage::decodeHeader(  getTokenValue(line, CD_FILENAME, false) ) );
            }
        }

        else if( line->ifind(ENCODING) == 0 ) {
            ret.setEncoding( getTokenValue(line, ENCODING));
        }

    }
    // move to the beginning of the content
    hdrlen += strlen(newline) + strlen(newline); // added 2 new line that separate the bodyparts
    // get bodypart content
    if( isAttach == false) { // || !ret.getFilename() ) {
        // this is not an attachment
        if(ret.getEncoding() && strcmp(ret.getEncoding(), "quoted-printable") == 0 ) {
            char *decoded = qp_decode( part.substr(hdrlen) );
            ret.setContent ( decoded );
            delete [] decoded;
        }
        else if (ret.getEncoding() && strcmp(ret.getEncoding(), "base64") == 0 ) {
            char *decoded = "";
            size_t len = 0;
            if( uudecode( part.substr(hdrlen), &decoded, &len ) ) {
                LOG.error("Error decoding content");
            }
            ret.setContent ( decoded );
            delete [] decoded;
        }
        else {
            bool found = true;
            if (part.substr(hdrlen).length() < 6) {
                StringBuffer s(part.substr(hdrlen));
                for (unsigned int i = 0; i < s.length(); i++) {
                    if (s.c_str()[i] != '\r' && s.c_str()[i] != '\n') {
                        found = true;
                        break;
                    } else {
                        found = false;
                    }
                }
            }
            if (found) {
                ret.setContent ( part.substr(hdrlen) );
            }
        }
    }
    else {
        LOG.debug("Attachment");
        ret.setContent( mkTempFileName( ret.getFilename() ) );
        LOG.debug("%s", ret.getContent());
        StringBuffer p = part.substr(hdrlen);
        if (p.length()) {
            LOG.debug("Saving...");
            if( convertAndSave(ret.getContent(), p.c_str(), ret.getEncoding()) ) {
                LOG.error("Error in convertAndSave");
            }
            else {
                LOG.debug("convertAndSave success");
            }
        }
    }
    LOG.debug("getBodyPart END");

    // return true if there are more parts
    return (next != StringBuffer::npos);
}

static void generateBoundary(StringBuffer& boundary)
{
    char buf[40];
    int i;

    *buf = '=';
    memset(buf+1, '-', 9*sizeof(char));
    for(i=10; i<36; i++) {
        buf[i] = '0' + rand() % 10;
    }
    buf[i]=0;
    boundary = buf;
}

static bool isAscii(const char *str){
    if(!str)
        return true;

    for(size_t i = 0; i < strlen(str); i++) {
        if (str[i] < 32 || str[i] > 126 ){
            return false;
        }
    }
    return true;
}

/**
* return the Importance tag given the importance. For MS pocket outlook
* the xPriority is 1-high, 3-normal, 5-low. At the moment it return
* the same value because also the client set the same values
*/
static StringBuffer convertForXPriority(StringBuffer importance) {
       
    return importance;
}

/**
* return the X-Priority tag given the importance. For MS pocket outlook
* the importance is 1-high, 3-normal, 5-low. It convert the long value
* into the text.
*/
static StringBuffer convertForImportance(StringBuffer importance) {
    
    StringBuffer ret(IMP_NORMAL);
    if (importance == "1") {
        ret = IMP_HIGH;
    } else if (importance == "5") {
        ret = IMP_LOW;
    } 
    return ret;
}

/*
* It encodes if needed and folds
*/
StringBuffer encodeHeader(StringBuffer line){

    if(isAscii(line))
        return line;

    StringBuffer ret;
    StringBuffer tmp;
    StringBuffer startPattern("=?utf-8?Q?");
    StringBuffer endPattern("?=");
    StringBuffer foldingPattern("\r\n ");
    int foldingLen = 64;

    char* qp = 0;
    qp = qp_encode(line);

    tmp += startPattern;
    tmp += qp;
    delete [] qp;

    // folding action
    unsigned long p = 0;
    while(p + foldingLen < tmp.length()) {
        ret.append(tmp.substr(p, foldingLen));
        ret.append(foldingPattern);
        ret.append(startPattern);
        p += foldingLen;
    }

    if (ret.length() > 0)
        tmp.append(tmp.substr(p, tmp.length() - p));

    ret = tmp;
    ret.append(endPattern);

    return ret;

}




//----------------------------------------------------------- Public Methods

/**
 * Format a mailmessage in a RFC2822 string
 */
char * MailMessage::format() {

    // If the message is empty, return null
    if ( empty() ) {
        LOG.debug("MailMessage::format: empty message.");
        return 0;
    }

    StringBuffer ret;

    LOG.debug("MailMessage::format START");

    if ( contentType.empty() ) {
        if ( attachments.size() ) {
            contentType = "multipart/mixed";
        }
        else {
            contentType = body.getMimeType();

            if (headers.size() > 0) {
                StringBuffer *line; int j = 0;
                for (line=(StringBuffer *)headers.front(); line; line=(StringBuffer *)headers.next() ) {
                    if (strstr(line->c_str(), "format=") != 0
                        || strstr(line->c_str(),"reply-type=") != 0 ) {
                            contentType.append("; ");
                            line->replaceAll(";", " ");
                            contentType.append(line->c_str());
                            headers.removeElementAt(j);
                            j--;
                         }
                     j++;
                }
            }

        }
    }
    if ( mimeVersion.empty() ) {
        mimeVersion = "1.0";
    }

    // Add generics headers
    ret.join((ArrayList &)headers, NL);
    // Add parsed headers
    ret += MIMEVERS; ret += mimeVersion; ret += NL;
    ret += MESSAGEID; ret += messageId; ret += NL;
    LOG.debug("MailMessage: From: %s\n", from.c_str());
    ret += FROM; ret += from; ret += NL;
    ret += TO; ret += to; ret += NL;
    if (cc.length() ) {
        ret += CC; ret += cc; ret += NL;
    }
    if (bcc.length() ) {
        ret += BCC; ret += bcc; ret += NL;
    }
    ret += DATE; ret += date.formatRfc822(); ret += NL;
    ret += SUBJECT;

    ret += encodeHeader(subject);

    ret += NL;

    // add priority
    ret += IMPORTANCE; ret += convertForImportance(importance); ret += NL;
    ret += X_PRIORITY; ret += convertForXPriority(importance); ret += NL;


    ret += MIMETYPE; ret += contentType; ret+= "; ";
    if (contentType.ifind(MULTIPART) != StringBuffer::npos ){
        if ( boundary.empty() ) {
            generateBoundary(boundary);
        }
        ret += "\n boundary=\""; ret += boundary;
        ret += "\"\n\nThis is a multi-part message in MIME format.\n";
        // Prepare a string with the boundary on a line alone
        StringBuffer bound = "\n--"; bound += boundary;
        // Body
        ret += bound; ret += NL;
        ret += formatBodyPart(body);
        ret += bound;
        // Attachments
        const BodyPart *part;
        for ( part=(const BodyPart *)attachments.front();
              part;
              part=(BodyPart *)attachments.next() ) {
            ret += NL;
            ret += formatBodyPart(*part);
            ret += bound;
        }
        ret += "--\n";

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?