File indexing completed on 2024-09-22 04:52:49

0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #ifndef IMAP_MESSAGE_H
0024 #define IMAP_MESSAGE_H
0025 
0026 #include <QSharedPointer>
0027 #include <QByteArray>
0028 #include <QDebug>
0029 #include <QVariant>
0030 #include <QDateTime>
0031 #include <QString>
0032 #include <QPair>
0033 #include "Data.h"
0034 #include "../Exceptions.h"
0035 #include "MailAddress.h"
0036 #include "../Model/MailboxTreeFwd.h"
0037 
0038 /** @short Namespace for IMAP interaction */
0039 namespace Imap
0040 {
0041 
0042 namespace Mailbox
0043 {
0044 class TreeItem;
0045 class TreeItemPart;
0046 }
0047 
0048 /** @short Classes for handling e-mail messages */
0049 namespace Message
0050 {
0051 
0052 /** @short Storage for envelope */
0053 class Envelope {
0054 public:
0055     QDateTime date;
0056     QString subject;
0057     QList<MailAddress> from;
0058     QList<MailAddress> sender;
0059     QList<MailAddress> replyTo;
0060     QList<MailAddress> to;
0061     QList<MailAddress> cc;
0062     QList<MailAddress> bcc;
0063     QList<QByteArray> inReplyTo;
0064     QByteArray messageId;
0065 
0066     Envelope() {}
0067     Envelope(const QDateTime &date, const QString &subject, const QList<MailAddress> &from,
0068              const QList<MailAddress> &sender, const QList<MailAddress> &replyTo,
0069              const QList<MailAddress> &to, const QList<MailAddress> &cc,
0070              const QList<MailAddress> &bcc, const QList<QByteArray> &inReplyTo,
0071              const QByteArray &messageId):
0072         date(date), subject(subject), from(from), sender(sender), replyTo(replyTo),
0073         to(to), cc(cc), bcc(bcc), inReplyTo(inReplyTo), messageId(messageId) {}
0074     static Envelope fromList(const QVariantList &items, const QByteArray &line, const int start);
0075     QTextStream &dump(QTextStream &s, const int indent) const;
0076 
0077     void clear();
0078 
0079 private:
0080     static QList<MailAddress> getListOfAddresses(const QVariant &in,
0081             const QByteArray &line, const int start);
0082     friend class Fetch;
0083 };
0084 
0085 
0086 /** @short Abstract parent of all Message classes
0087  *
0088  * A message can be either one-part (OneMessage) or multipart (MultiMessage)
0089  * */
0090 class AbstractMessage: public Responses::AbstractData {
0091 public:
0092     typedef QMap<QByteArray,QByteArray> bodyFldParam_t;
0093     typedef QPair<QByteArray, bodyFldParam_t> bodyFldDsp_t;
0094 
0095     // Common fields
0096     QByteArray mediaType;
0097     QByteArray mediaSubType;
0098     // Common optional fields
0099     bodyFldParam_t bodyFldParam;
0100     bodyFldDsp_t bodyFldDsp;
0101     QList<QByteArray> bodyFldLang;
0102     QByteArray bodyFldLoc;
0103     QVariant bodyExtension;
0104 
0105     virtual ~AbstractMessage() {}
0106     static QSharedPointer<AbstractMessage> fromList(const QVariantList &items, const QByteArray &line, const int start);
0107 
0108     static bodyFldParam_t makeBodyFldParam(const QVariant &list, const QByteArray &line, const int start);
0109     static bodyFldDsp_t makeBodyFldDsp(const QVariant &list, const QByteArray &line, const int start);
0110     static QList<QByteArray> makeBodyFldLang(const QVariant &input, const QByteArray &line, const int start);
0111 
0112     QTextStream &dump(QTextStream &s) const override { return dump(s, 0); }
0113     virtual QTextStream &dump(QTextStream &s, const int indent) const = 0;
0114     virtual Mailbox::TreeItemChildrenList createTreeItems(Mailbox::TreeItem *parent) const = 0;
0115 
0116     AbstractMessage(const QByteArray &mediaType, const QByteArray &mediaSubType, const bodyFldParam_t &bodyFldParam,
0117                     const bodyFldDsp_t &bodyFldDsp, const QList<QByteArray> &bodyFldLang, const QByteArray &bodyFldLoc,
0118                     const QVariant &bodyExtension):
0119         mediaType(mediaType), mediaSubType(mediaSubType), bodyFldParam(bodyFldParam), bodyFldDsp(bodyFldDsp),
0120         bodyFldLang(bodyFldLang), bodyFldLoc(bodyFldLoc), bodyExtension(bodyExtension) {}
0121 protected:
0122     static uint extractUInt(const QVariant &var, const QByteArray &line, const int start);
0123     static quint64 extractUInt64(const QVariant &var, const QByteArray &line, const int start);
0124     virtual void storeInterestingFields(Mailbox::TreeItemPart *p) const;
0125 };
0126 
0127 /** @short Abstract parent class for all non-multipart messages */
0128 class OneMessage: public AbstractMessage {
0129 public:
0130     QByteArray bodyFldId;
0131     QByteArray bodyFldDesc;
0132     QByteArray bodyFldEnc;
0133     quint64 bodyFldOctets;
0134     // optional fields specific to non-multipart:
0135     QByteArray bodyFldMd5;
0136     OneMessage(const QByteArray &mediaType, const QByteArray &mediaSubType,
0137                const bodyFldParam_t &bodyFldParam, const QByteArray &bodyFldId,
0138                const QByteArray &bodyFldDesc, const QByteArray &bodyFldEnc,
0139                const quint64 bodyFldOctets, const QByteArray &bodyFldMd5,
0140                const bodyFldDsp_t &bodyFldDsp,
0141                const QList<QByteArray> &bodyFldLang, const QByteArray &bodyFldLoc,
0142                const QVariant &bodyExtension):
0143         AbstractMessage(mediaType, mediaSubType, bodyFldParam, bodyFldDsp, bodyFldLang, bodyFldLoc, bodyExtension),
0144         bodyFldId(bodyFldId), bodyFldDesc(bodyFldDesc),
0145         bodyFldEnc(bodyFldEnc), bodyFldOctets(bodyFldOctets), bodyFldMd5(bodyFldMd5) {}
0146 
0147     bool eq(const AbstractData &other) const override;
0148 
0149 protected:
0150     void storeInterestingFields(Mailbox::TreeItemPart *p) const override;
0151 };
0152 
0153 /** @short Ordinary Message (body-type-basic in RFC3501) */
0154 class BasicMessage: public OneMessage {
0155 public:
0156     // nothing new, just stuff from OneMessage
0157     BasicMessage(const QByteArray &mediaType, const QByteArray &mediaSubType,
0158                  const bodyFldParam_t &bodyFldParam, const QByteArray &bodyFldId,
0159                  const QByteArray &bodyFldDesc, const QByteArray &bodyFldEnc,
0160                  const quint64 bodyFldOctets, const QByteArray &bodyFldMd5,
0161                  const bodyFldDsp_t &bodyFldDsp,
0162                  const QList<QByteArray> &bodyFldLang, const QByteArray &bodyFldLoc,
0163                  const QVariant &bodyExtension):
0164         OneMessage(mediaType, mediaSubType, bodyFldParam, bodyFldId,
0165                    bodyFldDesc, bodyFldEnc, bodyFldOctets, bodyFldMd5,
0166                    bodyFldDsp, bodyFldLang, bodyFldLoc, bodyExtension) {};
0167     QTextStream &dump(QTextStream &s, const int indent) const override;
0168     using OneMessage::dump;
0169     /* No need for "virtual bool eq( const AbstractData& other ) const" as
0170      * it's already implemented in OneMessage::eq() */
0171     Mailbox::TreeItemChildrenList createTreeItems(Mailbox::TreeItem *parent) const override;
0172 };
0173 
0174 /** @short A message holding another RFC822 message (body-type-msg) */
0175 class MsgMessage: public OneMessage {
0176 public:
0177     Envelope envelope;
0178     QSharedPointer<AbstractMessage> body;
0179     uint bodyFldLines;
0180     MsgMessage(const QByteArray &mediaType, const QByteArray &mediaSubType,
0181                const bodyFldParam_t &bodyFldParam, const QByteArray &bodyFldId,
0182                const QByteArray &bodyFldDesc, const QByteArray &bodyFldEnc,
0183                const quint64 bodyFldOctets, const QByteArray &bodyFldMd5,
0184                const bodyFldDsp_t &bodyFldDsp,
0185                const QList<QByteArray> &bodyFldLang, const QByteArray &bodyFldLoc,
0186                const QVariant &bodyExtension,
0187                const Envelope &envelope, const QSharedPointer<AbstractMessage> &body,
0188                const uint bodyFldLines):
0189         OneMessage(mediaType, mediaSubType, bodyFldParam, bodyFldId,
0190                    bodyFldDesc, bodyFldEnc, bodyFldOctets, bodyFldMd5,
0191                    bodyFldDsp, bodyFldLang, bodyFldLoc, bodyExtension),
0192         envelope(envelope), body(body), bodyFldLines(bodyFldLines) {}
0193     QTextStream &dump(QTextStream &s, const int indent) const override;
0194     using OneMessage::dump;
0195     bool eq(const AbstractData &other) const override;
0196     Mailbox::TreeItemChildrenList createTreeItems(Mailbox::TreeItem *parent) const override;
0197 };
0198 
0199 /** @short A text message (body-type-text) */
0200 class TextMessage: public OneMessage {
0201 public:
0202     uint bodyFldLines;
0203     TextMessage(const QByteArray &mediaType, const QByteArray &mediaSubType,
0204                 const bodyFldParam_t &bodyFldParam, const QByteArray &bodyFldId,
0205                 const QByteArray &bodyFldDesc, const QByteArray &bodyFldEnc,
0206                 const quint64 bodyFldOctets, const QByteArray &bodyFldMd5,
0207                 const bodyFldDsp_t &bodyFldDsp,
0208                 const QList<QByteArray> &bodyFldLang, const QByteArray &bodyFldLoc,
0209                 const QVariant &bodyExtension,
0210                 const uint bodyFldLines):
0211         OneMessage(mediaType, mediaSubType, bodyFldParam, bodyFldId,
0212                    bodyFldDesc, bodyFldEnc, bodyFldOctets, bodyFldMd5,
0213                    bodyFldDsp, bodyFldLang, bodyFldLoc, bodyExtension),
0214         bodyFldLines(bodyFldLines) {}
0215     QTextStream &dump(QTextStream &s, const int indent) const override;
0216     using OneMessage::dump;
0217     bool eq(const AbstractData &other) const override;
0218     Mailbox::TreeItemChildrenList createTreeItems(Mailbox::TreeItem *parent) const override;
0219 };
0220 
0221 /** @short Multipart message (body-type-mpart) */
0222 class MultiMessage: public AbstractMessage {
0223 public:
0224     QList<QSharedPointer<AbstractMessage> > bodies;
0225 
0226     MultiMessage(const QList<QSharedPointer<AbstractMessage> > &bodies,
0227                  const QByteArray &mediaSubType, const bodyFldParam_t &bodyFldParam,
0228                  const bodyFldDsp_t &bodyFldDsp,
0229                  const QList<QByteArray> &bodyFldLang, const QByteArray &bodyFldLoc,
0230                  const QVariant &bodyExtension):
0231         AbstractMessage("multipart", mediaSubType, bodyFldParam, bodyFldDsp, bodyFldLang, bodyFldLoc, bodyExtension),
0232         bodies(bodies) {}
0233     QTextStream &dump(QTextStream &s, const int indent) const override;
0234     using AbstractMessage::dump;
0235     bool eq(const AbstractData &other) const override;
0236     Mailbox::TreeItemChildrenList createTreeItems(Mailbox::TreeItem *parent) const override;
0237 protected:
0238     void storeInterestingFields(Mailbox::TreeItemPart *p) const override;
0239 };
0240 
0241 QTextStream &operator<<(QTextStream &stream, const Envelope &e);
0242 QTextStream &operator<<(QTextStream &stream, const AbstractMessage::bodyFldParam_t &p);
0243 QTextStream &operator<<(QTextStream &stream, const AbstractMessage::bodyFldDsp_t &p);
0244 QTextStream &operator<<(QTextStream &stream, const QList<QByteArray> &list);
0245 
0246 bool operator==(const Envelope &a, const Envelope &b);
0247 inline bool operator!=(const Envelope &a, const Envelope &b) { return !(a == b); }
0248 
0249 }
0250 
0251 }
0252 
0253 QDebug operator<<(QDebug dbg, const Imap::Message::Envelope &envelope);
0254 
0255 QDataStream &operator>>(QDataStream &stream, Imap::Message::Envelope &e);
0256 QDataStream &operator<<(QDataStream &stream, const Imap::Message::Envelope &e);
0257 
0258 Q_DECLARE_METATYPE(Imap::Message::Envelope)
0259 
0260 #endif /* IMAP_MESSAGE_H */