Example #1
0
QByteArray QxtMailAttachment::mimeData()
{
    bool isMultipart = false;
    QTextCodec* latin1 = QTextCodec::codecForName("latin1");

    if (qxt_d->attachments.count()) {
        if (!qxt_d->contentType.startsWith("multipart/", Qt::CaseInsensitive))
            setExtraHeader(QStringLiteral("Content-Type"), QStringLiteral("multipart/mixed"));
    }

    QByteArray rv = "Content-Type: " + qxt_d->contentType.toLatin1() + "\r\n";
    if (qxt_d->contentType.startsWith("multipart/", Qt::CaseInsensitive)) {
        isMultipart = true;
    }
    else {
        rv += "Content-Transfer-Encoding: base64\r\n";
    }

    foreach(const QString& r, qxt_d->extraHeaders.keys())
    {
        rv += qxt_fold_mime_header(r, extraHeader(r), latin1);
    }
    rv += "\r\n";

    const QByteArray& d = rawData();
    int chars = isMultipart? 73 : 57; // multipart preamble supposed to be 7bit latin1
    for (int pos = 0; pos < d.length(); pos += chars)
    {
        if (isMultipart) {
            rv += d.mid(pos, chars) + "\r\n";
        } else {
            rv += d.mid(pos, chars).toBase64() + "\r\n";
        }
    }

    if (isMultipart) {
        QMutableMapIterator<QString, QxtMailAttachment> it(qxt_d->attachments);
        while (it.hasNext()) {
            rv += "--" + qxt_d->boundary + "\r\n";
            rv += it.next().value().mimeData();
        }
        rv += "--" + qxt_d->boundary + "--\r\n";
    }

    return rv;
}
Example #2
0
QByteArray QxtMailMessage::rfc2822() const
{
    // Use quoted-printable if requested
	bool useQuotedPrintable = (extraHeader(QStringLiteral("Content-Transfer-Encoding")).toLower() == QLatin1String("quoted-printable"));
    // Use base64 if requested
	bool useBase64 = (extraHeader(QStringLiteral("Content-Transfer-Encoding")).toLower() == QLatin1String("base64"));
    // Check to see if plain text is ASCII-clean; assume it isn't if QP or base64 was requested
    QTextCodec* latin1 = QTextCodec::codecForName("latin1");
    bool bodyIsAscii = latin1->canEncode(body()) && !useQuotedPrintable && !useBase64;

    QHash<QString, QxtMailAttachment> attach = attachments();
    QByteArray rv;

	if (!sender().isEmpty() && !hasExtraHeader(QStringLiteral("From")))
    {
		rv += qxt_fold_mime_header(QStringLiteral("From"), sender(), latin1);
    }

    if (!qxt_d->rcptTo.isEmpty())
    {
		rv += qxt_fold_mime_header(QStringLiteral("To"), qxt_d->rcptTo.join(QStringLiteral(", ")), latin1);
    }

    if (!qxt_d->rcptCc.isEmpty())
    {
		rv += qxt_fold_mime_header(QStringLiteral("Cc"), qxt_d->rcptCc.join(QStringLiteral(", ")), latin1);
    }

    if (!subject().isEmpty())
    {
		rv += qxt_fold_mime_header(QStringLiteral("Subject"), subject(), latin1);
    }

    if (!bodyIsAscii)
    {
		if (!hasExtraHeader(QStringLiteral("MIME-Version")) && !attach.count())
            rv += "MIME-Version: 1.0\r\n";

        // If no transfer encoding has been requested, guess.
        // Heuristic: If >20% of the first 100 characters aren't
        // 7-bit clean, use base64, otherwise use Q-P.
        if(!bodyIsAscii && !useQuotedPrintable && !useBase64)
        {
            QString b = body();
            int nonAscii = 0;
            int ct = b.length();
            for (int i = 0; i < ct && i < 100; i++)
            {
				if (QXT_MUST_QP(b[i])) nonAscii++;
			}
            useQuotedPrintable = !(nonAscii > 20);
            useBase64 = !useQuotedPrintable;
        }
    }

    if (attach.count())
    {
        if (qxt_d->boundary.isEmpty())
            qxt_d->boundary = QUuid::createUuid().toString().toLatin1().replace("{", "").replace("}", "");
		if (!hasExtraHeader(QStringLiteral("MIME-Version")))
            rv += "MIME-Version: 1.0\r\n";
		if (!hasExtraHeader(QStringLiteral("Content-Type")))
            rv += "Content-Type: multipart/mixed; boundary=" + qxt_d->boundary + "\r\n";
    }
	else if (!bodyIsAscii && !hasExtraHeader(QStringLiteral("Content-Transfer-Encoding")))
    {
        if (!useQuotedPrintable)
        {
            // base64
            rv += "Content-Transfer-Encoding: base64\r\n";
        }
        else
        {
            // quoted-printable
            rv += "Content-Transfer-Encoding: quoted-printable\r\n";
        }
    }

    for(const QString& r: qxt_d->extraHeaders.keys())
    {
		if ((r.toLower() == QLatin1String("content-type") || r.toLower() == QLatin1String("content-transfer-encoding")) && attach.count())
        {
            // Since we're in multipart mode, we'll be outputting this later
            continue;
        }
		rv += qxt_fold_mime_header(r, extraHeader(r), latin1);
    }

    rv += "\r\n";

    if (attach.count())
    {
        // we're going to have attachments, so output the lead-in for the message body
        rv += "This is a message with multiple parts in MIME format.\r\n";
        rv += "--" + qxt_d->boundary + "\r\nContent-Type: ";
		if (hasExtraHeader(QStringLiteral("Content-Type")))
			rv += extraHeader(QStringLiteral("Content-Type")).toLatin1() + "\r\n";
        else
            rv += "text/plain; charset=UTF-8\r\n";
		if (hasExtraHeader(QStringLiteral("Content-Transfer-Encoding")))
        {
			rv += "Content-Transfer-Encoding: " + extraHeader(QStringLiteral("Content-Transfer-Encoding")).toLatin1() + "\r\n";
        }
        else if (!bodyIsAscii)
        {
            if (!useQuotedPrintable)
            {
                // base64
                rv += "Content-Transfer-Encoding: base64\r\n";
            }
            else
            {
                // quoted-printable
                rv += "Content-Transfer-Encoding: quoted-printable\r\n";
            }
        }
        rv += "\r\n";
    }

    if (bodyIsAscii)
    {
        QByteArray b = latin1->fromUnicode(body());
        int len = b.length();
        QByteArray line = "";
        QByteArray word = "";
        for (int i = 0; i < len; i++)
        {
            if (b[i] == '\n' || b[i] == '\r')
            {
                if (line.isEmpty()) 
                {
                    line = word;
                    word = "";
                }
                else if (line.length() + word.length() + 1 <= 78)
                {
                    line = line + ' ' + word;
                    word = "";
                }
                if(line[0] == '.')
                    rv += ".";
                rv += line + "\r\n";
                if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1])
                {
                    // If we're looking at a CRLF pair, skip the second half
                    i++;
                }
                line = word;
            }
            else if (b[i] == ' ')
            {
                if (line.length() + word.length() + 1 > 78)
                {
                    if(line[0] == '.')
                        rv += ".";
                    rv += line + "\r\n";
                    line = word;
                }
                else if (line.isEmpty())
                {
                    line = word;
                }
                else
                {
                    line = line + ' ' + word;
                }
                word = "";
            }
            else
            {
                word += b[i];
            }
        }
        if (line.length() + word.length() + 1 > 78)
        {
            if(line[0] == '.')
                rv += ".";
            rv += line + "\r\n";
            line = word;
        }
        else if (!word.isEmpty())
        {
            line += ' ' + word;
        }
        if(!line.isEmpty()) {
            if(line[0] == '.')
                rv += ".";
            rv += line + "\r\n";
        }
    }
    else if (useQuotedPrintable)
    {
        QByteArray b = body().toUtf8();
        int ct = b.length();
        QByteArray line;
        for (int i = 0; i < ct; i++)
        {
            if(b[i] == '\n' || b[i] == '\r')
            {
                if(line[0] == '.')
                    rv += ".";
                rv += line + "\r\n";
                line = "";
                if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1])
                {
                    // If we're looking at a CRLF pair, skip the second half
                    i++;
                }
            }
            else if (line.length() > 74)
            {
                rv += line + "=\r\n";
                line = "";
            }
            if (QXT_MUST_QP(b[i]))
            {
                line += "=" + b.mid(i, 1).toHex().toUpper();
            }
            else
            {
                line += b[i];
            }
        }
        if(!line.isEmpty()) {
            if(line[0] == '.')
                rv += ".";
            rv += line + "\r\n";
        }
    }
    else /* base64 */
    {
        QByteArray b = body().toUtf8().toBase64();
        int ct = b.length();
        for (int i = 0; i < ct; i += 78)
        {
            rv += b.mid(i, 78) + "\r\n";
        }
    }

    if (attach.count())
    {
        for(const QString& filename: attach.keys())
        {
            rv += "--" + qxt_d->boundary + "\r\n";
			rv += qxt_fold_mime_header(QStringLiteral("Content-Disposition"), QDir(filename).dirName(), latin1, "attachment; filename=");
            rv += attach[filename].mimeData();
        }
        rv += "--" + qxt_d->boundary + "--\r\n";
    }

    return rv;
}