mailmessage.cpp

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

CPP
1,042
字号
/*
 * Funambol is a mobile platform developed by Funambol, Inc. 
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission 
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License 
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 * 
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably 
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include "base/fscapi.h"
#include "base/util/utils.h"
#include "base/quoted-printable.h"
#include "base/Log.h"
#include "spds/spdsutils.h"
#include "spds/MailMessage.h"
#include "base/globalsdef.h"

USE_NAMESPACE

//------------------------------------------------------------------ Defines

// Headers names
#define NL          "\n"
#define FROM        "From: "
#define TO          "To: "
#define CC          "CC: "
#define BCC         "BCC: "
#define DATE        "Date: "
#define RECEIVED    "Received:"
#define SUBJECT     "Subject: "
#define MIMETYPE    "Content-Type: "
#define CT_NAME     "name="
#define CT_CHARSET  "charset="
#define MIMEVERS    "Mime-Version: "
#define MESSAGEID   "Message-ID: "
#define DISPOSITION "Content-Disposition:"
#define CD_FILENAME "filename="
#define ENCODING    "Content-Transfer-Encoding: "
#define IMPORTANCE  "Importance: "
#define X_PRIORITY  "X-Priority: "

#define IMP_NORMAL  "normal"
#define IMP_HIGH    "high"
#define IMP_LOW     "low"

#define MULTIPART   "multipart/"


// Header names' length
static const unsigned char FROM_LEN = strlen(FROM);
static const unsigned char TO_LEN   = strlen(TO);
static const unsigned char CC_LEN   = strlen(CC);
static const unsigned char BCC_LEN  = strlen(BCC);
static const unsigned char DATE_LEN  = strlen(DATE);
static const unsigned char SUBJECT_LEN = strlen(SUBJECT);
static const unsigned char MIMETYPE_LEN = strlen(MIMETYPE);
static const unsigned char MIMEVERS_LEN = strlen(MIMEVERS);
static const unsigned char MESSAGEID_LEN = strlen(MESSAGEID);
static const unsigned char DISPOSITION_LEN = strlen(DISPOSITION);
static const unsigned char ENCODING_LEN = strlen(ENCODING);
static const unsigned char IMPORTANCE_LEN = strlen(IMPORTANCE);
static const unsigned char X_PRIORITY_LEN = strlen(X_PRIORITY);

//---------------------------------------------------------------- Accessors

const char *MailMessage::getTo() const { return to.c_str(); }
void MailMessage::setTo(const char *to) { this->to = to; }

const char *MailMessage::getFrom() const { return from.c_str(); }
void MailMessage::setFrom(const char *from) { this->from = from; }

const char *MailMessage::getCc() const { return cc.c_str(); }
void MailMessage::setCc(const char *cc) { this->cc = cc; }

const char *MailMessage::getBcc() const { return bcc.c_str(); }
void MailMessage::setBcc(const char *bcc) { this->bcc = bcc; }

//        int addHeader(const char *name, const char *content);
const char *MailMessage::getSubject() const { return subject.c_str(); }
void MailMessage::setSubject(const char *subj) { subject = subj; }

const BasicTime& MailMessage::getDate() const { return date; }
void MailMessage::setDate(const BasicTime& v) { date = v; }

const BasicTime& MailMessage::getReceived() const { return received; }

const char * MailMessage::getContentType() const { return contentType; }
void MailMessage::setContentType(const char *val) { contentType = val; }

const char * MailMessage::getBoundary() const { return boundary; }
void MailMessage::setBoundary(const char *val) { boundary = val; }

const char * MailMessage::getMimeVersion() const { return mimeVersion; }
void MailMessage::setMimeVersion(const char *val) { mimeVersion = val; }

const char * MailMessage::getMessageId() const { return messageId; }
void MailMessage::setMessageId(const char *val) { messageId = val; }

const char* MailMessage::getEntryID() { return entryId.c_str(); }
void MailMessage::setEntryID(const char* id) { entryId = id; }

const char* MailMessage::getImportance() { return importance; }
void MailMessage::setImportance(const char* imp) { importance = imp; }


BodyPart & MailMessage::getBody() { return body; }
void MailMessage::setBody(BodyPart &body) { this->body = body; }

// Alternate representation
//BodyPart * MailMessage::getAlternate() { return alternate; };
//void MailMessage::setAlternate(BodyPart &alt) { alternate = new BodyPart(alt); };

BodyPart * MailMessage::getFirstAttachment() {
    return (BodyPart *)attachments.front();
}

BodyPart * MailMessage::getNextAttachment() {
    return (BodyPart *)attachments.next();
}

int MailMessage::addAttachment(BodyPart &body) {
    return attachments.add(body);
}

int MailMessage::attachmentCount() {
    return attachments.size();
}

//----------------------------------------------------------- Static Functions

static StringBuffer formatBodyPart(const BodyPart &part)
{
    StringBuffer ret;    
    LOG.debug("FormatBodyPart START");

    ret = MIMETYPE;
    
    ret += part.getMimeType(); ret += ";";
    if (!part.getFilename()) {
        LOG.debug("It doesn't contains an attachment. It is the body");
        ret +=" "; ret += CT_CHARSET; ret += part.getCharset(); 
    }
    ret += NL;
    
    if( part.getFilename() ) {
        ret += "        "; ret += CT_NAME; ret += "\""; ret += part.getFilename(); ret += "\"\n";
    }
    if( part.getEncoding() ) {
        ret += ENCODING; ret += part.getEncoding(); ret += NL;
    }
    if( part.getFilename() ) {
        if( part.getDisposition() ) {
            ret += DISPOSITION; ret += part.getDisposition(); ret += ";\n";
        }
        else {
            ret += DISPOSITION; ret += "attachment;\n";
        }

        ret += "      "; ret += CD_FILENAME; ret += "\""; ret += part.getFilename();
        ret += "\"\n";
    }
    // End of part headers
    ret += NL;
    // Content
    if( part.getFilename() ) {
        char *content = loadAndConvert(part.getContent(), part.getEncoding());
        ret += content;
        delete [] content;
    }
    else
        ret += part.getContent();

    LOG.debug("FormatBodyPart END");
    return ret;
}

inline static size_t findNewLine(StringBuffer &str, size_t offset) {
    size_t nl = str.find("\n", offset)+1;
    if(nl == StringBuffer::npos)
        return nl;
    return (str[nl] == '\r') ? nl+1 : nl ;
}

static size_t getHeadersLen(StringBuffer &s, StringBuffer &newline)
{
    // detect the newline used in headers
    size_t pos1 = s.find("\n");
    if(pos1 == StringBuffer::npos){
        LOG.error("MailMessage: no newlines in message?");
        return pos1;
    }
    size_t pos2 = pos1 + 1 ;

    while (s[pos1-1] == '\r'){
        pos1--;
    }
    newline = s.substr(pos1, pos2-pos1);

    StringBuffer emptyline = newline + newline ;

    // Split headers and body
    size_t hdrlen = s.find(emptyline);
    if(hdrlen == StringBuffer::npos) {
        // Empty body, get the message anyway.
        hdrlen = s.length();
    }
    return hdrlen;
}


static StringBuffer getTokenValue(const StringBuffer* line, const char* token, bool toLower = true) {

    StringBuffer ret("");
    if (line->ifind(token) == StringBuffer::npos)
        return ret;

    size_t begin = line->ifind(token) + strlen(token);
    size_t end = begin;
    size_t quote = line->find("\"", begin);
    size_t semicolon = line->find(";", begin);

    if (quote != StringBuffer::npos){
        if (semicolon != StringBuffer::npos) {
            if (quote < semicolon) {
                begin = quote + 1;
                end = line->find("\"", begin) ;
            } else {
                end = line->find(";", begin) ;
            }
        } else {
            begin = quote + 1;
            end = line->find("\"", begin) ;
        }
    } else {
        end = line->find(";", begin) ;
        if (end == StringBuffer::npos) {
            end = line->find(" ", begin);
        }
    }
    ret = line->substr(begin, end-begin);
    if (toLower) {
        ret = ret.lowerCase();
    }
    return ret;
}


StringBuffer MailMessage::decodeHeader(StringBuffer line) {

    if (!line || line.empty()) {
        return line;
    }

    size_t startPos = 0;
    StringBuffer ret;
    StringBuffer charset;
    while( (startPos = line.find("=?", startPos)) != StringBuffer::npos) {
        // Skip the '=?'
        startPos += 2;
        // Find the first '?'
        size_t firstMark = line.find("?", startPos);
        if (firstMark == StringBuffer::npos) {
            LOG.error("Invalid encoded header");
            return line;
        }
        // Find the second '?'
        size_t secondMark = line.find("?", firstMark+1);
        if (secondMark == StringBuffer::npos) {
            LOG.error("Invalid encoded header");
            return line;
        }
        // Find the final '?='
        size_t endPos = line.find("?=", secondMark+1);
        if (endPos == StringBuffer::npos) {
            LOG.error("Invalid encoded header");
            return line;
        }

        charset = line.substr(startPos, firstMark - startPos);
        StringBuffer encoding = line.substr(firstMark+1, secondMark - (firstMark + 1));
        StringBuffer text = line.substr(secondMark+1, endPos - (secondMark + 1));

        if (encoding.icmp("Q")) {
            // quoted-printable
            text.replaceAll("_", " ");
            char* dec = qp_decode(text);
            if (startPos >= 2 &&  ret.length() == 0) {
                ret += line.substr(0, startPos - 2);
            }

            ret += dec;
            delete [] dec;
        }
        else if (encoding.icmp("B")){
        // base64
            char* dec = new char[text.length()];
            int len = b64_decode((void *)dec, text);
            dec[len]=0;
            if (startPos >= 2 &&  ret.length() == 0) {
                ret += line.substr(0, startPos - 2);
            }
            ret += dec;
            delete [] dec;
        }

        startPos = endPos;
    }

    if (ret.length() == 0) {
        ret += line;
    }

    WCHAR* wret = toWideChar(ret, charset);
    ret.set(NULL);
    char* t = toMultibyte(wret);
    ret.set(t);
    if (wret) {delete [] wret;}
    if (t) {delete [] t;}
    return ret;
}
/**
 * Get the next bodypart from the message body string.

⌨️ 快捷键说明

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