diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-02 17:27:07 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-04 12:52:21 +0200 |
| commit | 5f22f80b6b5cef5e768086338ae4b22120f3e67c (patch) | |
| tree | e127827da5a248fd8e6c80397f896a1f6d302ac0 /src/mimeparser.h | |
| parent | 72b56d0beca6d640c724eabc73a3ee45cf04bfea (diff) | |
| download | qtmaildir-5f22f80b6b5cef5e768086338ae4b22120f3e67c.tar.gz qtmaildir-5f22f80b6b5cef5e768086338ae4b22120f3e67c.zip | |
feat: add MimeParser with GMime and safe attachment naming
Diffstat (limited to 'src/mimeparser.h')
| -rw-r--r-- | src/mimeparser.h | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/mimeparser.h b/src/mimeparser.h new file mode 100644 index 0000000..27a239f --- /dev/null +++ b/src/mimeparser.h @@ -0,0 +1,64 @@ +#pragma once + +#include <QByteArray> +#include <QHash> +#include <QList> +#include <QString> + +/// An inline part referenced by a cid: URL from the HTML body. +struct InlinePart +{ + QString mimeType; + QByteArray data; +}; + +struct Attachment +{ + QString filename; ///< As it appeared in the message. Untrusted. + QString mimeType; + QByteArray data; + + /// filename reduced to a basename safe to join onto a directory. + /// Attacker-controlled input: a filename may contain path separators or + /// "..", so anything that could escape the target directory is stripped. + /// Returns a generated name when nothing usable remains. + QString safeFilename() const; + + /// Writes the attachment into directory. Returns the full path written, or + /// an empty string on failure with *error set. + QString saveTo(const QString &directory, QString *error) const; +}; + +struct ParsedMessage +{ + bool ok = false; + QString error; + + QString subject; + QString from; + QString to; + QString cc; + QString date; + QString messageId; + + QString plainBody; + QString htmlBody; + + QHash<QString, InlinePart> inlineParts; ///< Keyed by Content-ID, no <>. + QList<Attachment> attachments; + + bool hasHtml() const { return !htmlBody.isEmpty(); } +}; + +/// Parses a single message file using GMime. +/// +/// Hand-rolling this would mean reimplementing RFC 2047 encoded words, RFC 2231 +/// parameter continuations, transfer encodings, and charset conversion, plus +/// tolerance for malformed real-world mail. +class MimeParser +{ +public: + MimeParser(); + + ParsedMessage parse(const QString &filePath) const; +}; |
