diff options
author | Saturneric <[email protected]> | 2021-07-14 18:01:59 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2021-07-14 18:01:59 +0000 |
commit | 74fc3e78aadec387f561811b496061440e70cf82 (patch) | |
tree | b7cc8483042dff1dc6f5269095a17e1750009d3d | |
parent | Merge from github/main. (diff) | |
parent | Update documentation (diff) | |
download | GpgFrontend-74fc3e78aadec387f561811b496061440e70cf82.tar.gz GpgFrontend-74fc3e78aadec387f561811b496061440e70cf82.zip |
Merge branch 'develop' into main
# Conflicts:
# README.md
# docs/quick-start.md
Diffstat (limited to '')
45 files changed, 2373 insertions, 1198 deletions
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 22f268b2..3ad2246c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,7 +75,7 @@ jobs: shell: msys2 {0} run: | pacman --noconfirm -S --needed mingw-w64-x86_64-gcc mingw-w64-x86_64-make mingw-w64-x86_64-cmake autoconf automake mingw-w64-x86_64-qt-creator mingw-w64-x86_64-gpgme - pacman --noconfirm -S --needed make texinfo + pacman --noconfirm -S --needed make texinfo zip if: matrix.os == 'windows-latest' - name: Build gpg-error (Linux) @@ -132,6 +132,10 @@ jobs: run: cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -j 2 if: matrix.os == 'ubuntu-16.04' || matrix.os == 'macos-latest' + - name: Get Short SHA of Commit + id: vars + run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" + - name: Package App Bundle (macOS) run: | macdeployqt ${{github.workspace}}/build/release/GpgFrontend.app @@ -139,6 +143,7 @@ jobs: hdiutil create ${{github.workspace}}/build/tmp/tmp.dmg -ov -volname "GpgFrontend" -fs HFS+ -srcfolder ${{github.workspace}}/build/release/ mkdir ${{github.workspace}}/build/artifactOut hdiutil convert ${{github.workspace}}/build/tmp/tmp.dmg -format UDZO -o ${{github.workspace}}/build/artifactOut/GpgFrontend.dmg + mv ${{github.workspace}}/build/artifactOut/GpgFrontend.dmg ${{github.workspace}}/build/artifactOut/GpgFrontend-${{steps.vars.outputs.sha_short}}-x86_64.dmg if: matrix.os == 'macos-latest' - name: Package App Image (Linux) @@ -150,7 +155,7 @@ jobs: ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/release/gpgfrontend/usr/share/applications/*.desktop -appimage if: matrix.os == 'ubuntu-16.04' - - name: Configure CMake & Build Binary(Windows) + - name: Configure CMake & Build Binary (Windows) shell: msys2 {0} run: | cd $(echo "/${{github.workspace}}" | sed 's/\\/\//g' | sed 's/://') @@ -160,10 +165,6 @@ jobs: cmake --build . --config ${{env.BUILD_TYPE}} -- -j 2 if: matrix.os == 'windows-latest' - - name: Get Short SHA of Commit - id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - name: Upload Artifact(Linux) uses: actions/upload-artifact@master with: @@ -110,12 +110,13 @@ awesome operations. #### macOS -0. If command `gpg` is not avaliable, please use homebrew to install it first. +0. If command `gpg` is not available, please use homebrew to install it first. 1. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) macOS edition from the latest release -2. Double-Click GpgFrontend-***.dmg to load it +2. Double-Click GpgFrontend.dmg to load it - macOS will automatically decompress the zip file and then you will be able to see the dmg -3. Double click and run it. If it satisfies you, you can drag it into your Application folder. +3. Double click and run it (due to macOS security policy, you may need a little more step). +4. If it satisfies you, you can drag it into your Application folder. #### Debian/Ubuntu/CentOS diff --git a/include/MainWindow.h b/include/MainWindow.h index 1137dfed..20f9a0b5 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -26,7 +26,6 @@ #define __GPGWIN_H__ #include "gpg/GpgConstants.h" -#include "ui/widgets/Attachments.h" #include "ui/KeyMgmt.h" #include "ui/widgets/TextEdit.h" #include "ui/FileEncryptionDialog.h" @@ -393,9 +392,8 @@ private: KeyList *mKeyList; InfoBoardWidget *infoBoard; - Attachments *mAttachments; /**< TODO */ - GpgME::GpgContext *mCtx; /**< TODO */ - KeyMgmt *keyMgmt; /**< TODO */ + GpgME::GpgContext *mCtx; + KeyMgmt *keyMgmt; KeyServerImportDialog *importDialog; /**< TODO */ QNetworkAccessManager *networkAccessManager; diff --git a/include/Mime.h b/include/Mime.h deleted file mode 100644 index c86ac630..00000000 --- a/include/Mime.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar 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 General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#ifndef __MIME_H__ -#define __MIME_H__ - -#include <GpgFrontend.h> -#include <utility> - -class HeadElem { -public: - QString name; - QString value; - QHash<QString, QString> params; - - /* QDataStream & operator<<(QDataStream& Stream, const HeadElem& H) - { - return Stream << H.name << " : " << H.value; - }*/ - -}; - -class Header { -public: - QList<HeadElem> headElems; - - Header() = default; - - explicit Header(QList<HeadElem> heads) { - headElems = std::move(heads); - } - - [[maybe_unused]] void setHeader(QList<HeadElem> heads) { - headElems = std::move(heads); - } - - QString getValue(const QString &key) { - foreach(HeadElem tmp, headElems) { - //qDebug() << "gv: " << tmp.name << ":" << tmp.value; - if (tmp.name == key) - return tmp.value; - } - return ""; - } - - QHash<QString, QString> getParams(const QString &key) { - foreach(HeadElem tmp, headElems) { - //qDebug() << "gv: " << tmp.name << ":" << tmp.value; - if (tmp.name == key) - //return tmp.value; - return tmp.params; - } - return *(new QHash<QString, QString>()); - } - - QString getParam(const QString &key, const QString &pKey) { - foreach(HeadElem tmp, headElems) { - //qDebug() << "gv: " << tmp.name << ":" << tmp.value; - if (tmp.name == key) - return tmp.params.value(pKey); - } - return ""; - } - - -}; - -class MimePart { -public: - Header header; - QByteArray body; - - - - /* QDataStream & operator<<(QDataStream& Stream, const Part& P) - { - foreach(HeadElem tmp, header) { - Stream << tmp << "\n"; - } - return Stream; - }*/ -}; - -class Mime { - -public: - explicit Mime(QByteArray *message); // Constructor - ~Mime(); // Destructor - static bool isMultipart(QByteArray *message); - - static bool isMime(const QByteArray *message); - - QList<MimePart> parts() { - return mPartList; - } - - void splitParts(QByteArray *message); - - static Header getHeader(const QByteArray *message); - - static Header parseHeader(QByteArray *header); - - static void quotedPrintableDecode(const QByteArray &in, QByteArray &out); - -private: - QList<MimePart> mPartList; -}; - -#endif // __MIME_H__ diff --git a/include/smtp/SmtpMime b/include/smtp/SmtpMime new file mode 100644 index 00000000..940996b8 --- /dev/null +++ b/include/smtp/SmtpMime @@ -0,0 +1,31 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef SMTPMIME_H +#define SMTPMIME_H + +#include "smtpclient.h" +#include "mimepart.h" +#include "mimehtml.h" +#include "mimeattachment.h" +#include "mimemessage.h" +#include "mimetext.h" +#include "mimeinlinefile.h" +#include "mimefile.h" + +#endif // SMTPMIME_H diff --git a/include/smtp/emailaddress.h b/include/smtp/emailaddress.h new file mode 100644 index 00000000..90e4c1e9 --- /dev/null +++ b/include/smtp/emailaddress.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef EMAILADDRESS_H +#define EMAILADDRESS_H + +#include <QObject> + +#include "smtpexports.h" + +class SMTP_EXPORT EmailAddress : public QObject { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + EmailAddress() = default; + + explicit EmailAddress(const QString &address, const QString &name = ""); + + ~EmailAddress() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + void setName(const QString &name); + + void setAddress(const QString &address); + + [[nodiscard]] const QString &getName() const; + + [[nodiscard]] const QString &getAddress() const; + + /* [2] --- */ + + +private: + + /* [3] Private members */ + + QString name; + QString address; + + /* [3] --- */ +}; + +#endif // EMAILADDRESS_H diff --git a/include/smtp/mimeattachment.h b/include/smtp/mimeattachment.h new file mode 100644 index 00000000..6b98a65a --- /dev/null +++ b/include/smtp/mimeattachment.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEATTACHMENT_H +#define MIMEATTACHMENT_H + +#include <QFile> +#include "mimepart.h" +#include "mimefile.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeAttachment : public MimeFile { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + explicit MimeAttachment(QFile *file); + + MimeAttachment(const QByteArray &stream, const QString &fileName); + + ~MimeAttachment() override; + + /* [1] --- */ + +protected: + + /* [2] Protected methods */ + + void prepare() override; + + /* [2] --- */ +}; + +#endif // MIMEATTACHMENT_H diff --git a/include/smtp/mimecontentformatter.h b/include/smtp/mimecontentformatter.h new file mode 100644 index 00000000..e6e3637f --- /dev/null +++ b/include/smtp/mimecontentformatter.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMECONTENTFORMATTER_H +#define MIMECONTENTFORMATTER_H + +#include <QObject> +#include <QByteArray> + +#include "smtpexports.h" + +class SMTP_EXPORT MimeContentFormatter : public QObject { +Q_OBJECT +public: + explicit MimeContentFormatter(int max_length = 76); + + void setMaxLength(int l); + + [[nodiscard]] int getMaxLength() const; + + [[nodiscard]] QString format(const QString &content, bool quotedPrintable = false) const; + +protected: + int max_length; + +}; + +#endif // MIMECONTENTFORMATTER_H diff --git a/include/smtp/mimefile.h b/include/smtp/mimefile.h new file mode 100644 index 00000000..46903da9 --- /dev/null +++ b/include/smtp/mimefile.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEFILE_H +#define MIMEFILE_H + +#include "mimepart.h" +#include <QFile> + +#include "smtpexports.h" + +class SMTP_EXPORT MimeFile : public MimePart { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + MimeFile(const QByteArray &stream, const QString &fileName); + + explicit MimeFile(QFile *f); + + ~MimeFile() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + QFile *file; + + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ + +}; + +#endif // MIMEFILE_H diff --git a/include/smtp/mimehtml.h b/include/smtp/mimehtml.h new file mode 100644 index 00000000..8ce8c454 --- /dev/null +++ b/include/smtp/mimehtml.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEHTML_H +#define MIMEHTML_H + +#include "mimetext.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeHtml : public MimeText { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + explicit MimeHtml(const QString &html = ""); + + ~MimeHtml() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + void setHtml(const QString &html); + + [[nodiscard]] const QString &getHtml() const; + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ +}; + +#endif // MIMEHTML_H diff --git a/include/smtp/mimeinlinefile.h b/include/smtp/mimeinlinefile.h new file mode 100644 index 00000000..916f7b76 --- /dev/null +++ b/include/smtp/mimeinlinefile.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEINLINEFILE_H +#define MIMEINLINEFILE_H + +#include "mimefile.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeInlineFile : public MimeFile { +public: + + /* [1] Constructors and Destructors */ + + explicit MimeInlineFile(QFile *f); + + ~MimeInlineFile() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ +}; + +#endif // MIMEINLINEFILE_H diff --git a/include/smtp/mimemessage.h b/include/smtp/mimemessage.h new file mode 100644 index 00000000..24e4f108 --- /dev/null +++ b/include/smtp/mimemessage.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEMESSAGE_H +#define MIMEMESSAGE_H + +#include "mimepart.h" +#include "mimemultipart.h" +#include "emailaddress.h" +#include <QList> + +#include "smtpexports.h" + +class SMTP_EXPORT MimeMessage : public QObject { +public: + + enum RecipientType { + To, // primary + Cc, // carbon copy + Bcc // blind carbon copy + }; + + /* [1] Constructors and Destructors */ + + explicit MimeMessage(bool createAutoMimeConent = true); + + ~MimeMessage() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + void setSender(EmailAddress *e); + + void addRecipient(EmailAddress *rcpt, RecipientType type = To); + + void addTo(EmailAddress *rcpt); + + void addCc(EmailAddress *rcpt); + + void addBcc(EmailAddress *rcpt); + + void setSubject(const QString &subject); + + void addPart(MimePart *part); + + void setReplyTo(EmailAddress *rto); + + void setInReplyTo(const QString &inReplyTo); + + void setHeaderEncoding(MimePart::Encoding); + + [[nodiscard]] const EmailAddress &getSender() const; + + [[nodiscard]] const QList<EmailAddress *> &getRecipients(RecipientType type = To) const; + + [[nodiscard]] const QString &getSubject() const; + + [[nodiscard]] const QList<MimePart *> &getParts() const; + + [[nodiscard]] const EmailAddress *getReplyTo() const; + + MimePart &getContent(); + + void setContent(MimePart *content); + /* [2] --- */ + + + /* [3] Public methods */ + + virtual QString toString(); + + /* [3] --- */ + +protected: + + /* [4] Protected members */ + + EmailAddress *sender{}; + EmailAddress *replyTo; + QList<EmailAddress *> recipientsTo, recipientsCc, recipientsBcc; + QString subject; + QString mInReplyTo; + MimePart *content; + bool autoMimeContentCreated; + + MimePart::Encoding hEncoding; + + /* [4] --- */ + + +}; + +#endif // MIMEMESSAGE_H diff --git a/include/smtp/mimemultipart.h b/include/smtp/mimemultipart.h new file mode 100644 index 00000000..b829a66f --- /dev/null +++ b/include/smtp/mimemultipart.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEMULTIPART_H +#define MIMEMULTIPART_H + +#include "mimepart.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeMultiPart : public MimePart { +Q_OBJECT +public: + /* [0] Enums */ + enum MultiPartType { + Mixed = 0, // RFC 2046, section 5.1.3 + Digest = 1, // RFC 2046, section 5.1.5 + Alternative = 2, // RFC 2046, section 5.1.4 + Related = 3, // RFC 2387 + Report = 4, // RFC 6522 + Signed = 5, // RFC 1847, section 2.1 + Encrypted = 6 // RFC 1847, section 2.2 + }; + + /* [0] --- */ + + /* [1] Constructors and Destructors */ + explicit MimeMultiPart(MultiPartType type = Related); + + /* [1] --- */ + + /* [2] Getters and Setters */ + + void setMimeType(MultiPartType type); + + [[nodiscard]] MultiPartType getMimeType() const; + + [[nodiscard]] const QList<MimePart *> &getParts() const; + + /* [2] --- */ + + /* [3] Public methods */ + + void addPart(MimePart *part); + + void prepare() override; + + /* [3] --- */ + +protected: + QList<MimePart *> parts; + + MultiPartType type; +}; + +#endif // MIMEMULTIPART_H diff --git a/include/smtp/mimepart.h b/include/smtp/mimepart.h new file mode 100644 index 00000000..1a1386de --- /dev/null +++ b/include/smtp/mimepart.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEPART_H +#define MIMEPART_H + +#include "mimecontentformatter.h" +#include <QObject> + +#include "smtpexports.h" + +class SMTP_EXPORT MimePart : public QObject { +Q_OBJECT +public: + /* [0] Enumerations */ + enum Encoding { + _7Bit, _8Bit, Base64, QuotedPrintable + }; + + /* [0] --- */ + + /* [1] Constructors and Destructors */ + + MimePart(); + + ~MimePart() = default; + + /* [1] --- */ + + /* [2] Getters and Setters */ + + [[nodiscard]] const QString &getHeader() const; + + [[nodiscard]] const QByteArray &getContent() const; + + void setContent(const QByteArray &content); + + void setHeader(const QString &header); + + void addHeaderLine(const QString &line); + + void setContentId(const QString &cId); + + [[nodiscard]] const QString &getContentId() const; + + void setContentName(const QString &cName); + + [[nodiscard]] const QString &getContentName() const; + + void setContentType(const QString &cType); + + [[nodiscard]] const QString &getContentType() const; + + void setCharset(const QString &charset); + + [[nodiscard]] const QString &getCharset() const; + + void setEncoding(Encoding enc); + + [[nodiscard]] Encoding getEncoding() const; + + MimeContentFormatter &getContentFormatter(); + + /* [2] --- */ + + /* [3] Public methods */ + + virtual QString toString(); + + virtual void prepare(); + + /* [3] --- */ + +protected: + /* [4] Protected members */ + + QString header; + QByteArray content; + + QString cId; + QString cName; + QString cType; + QString cCharset; + QString cBoundary; + Encoding cEncoding; + + QString mimeString; + bool prepared; + + MimeContentFormatter formatter; + + /* [4] --- */ +}; + +#endif // MIMEPART_H diff --git a/include/smtp/mimetext.h b/include/smtp/mimetext.h new file mode 100644 index 00000000..c21a1c5e --- /dev/null +++ b/include/smtp/mimetext.h @@ -0,0 +1,62 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMETEXT_H +#define MIMETEXT_H + +#include "mimepart.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeText : public MimePart { +public: + + /* [1] Constructors and Destructors */ + + explicit MimeText(const QString &text = ""); + + ~MimeText() override; + + /* [1] --- */ + + + /* [2] Getters and Setters*/ + + void setText(const QString &text); + + [[nodiscard]] const QString &getText() const; + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + QString text; + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ + +}; + +#endif // MIMETEXT_H diff --git a/include/smtp/quotedprintable.h b/include/smtp/quotedprintable.h new file mode 100644 index 00000000..00ca3cf8 --- /dev/null +++ b/include/smtp/quotedprintable.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef QUOTEDPRINTABLE_H +#define QUOTEDPRINTABLE_H + +#include <QObject> +#include <QByteArray> + +#include "smtpexports.h" + +class SMTP_EXPORT QuotedPrintable : public QObject { +Q_OBJECT +public: + + static QString encode(const QByteArray &input); + + static QByteArray decode(const QString &input); + +private: + QuotedPrintable(); +}; + +#endif // QUOTEDPRINTABLE_H diff --git a/include/smtp/smtpclient.h b/include/smtp/smtpclient.h new file mode 100644 index 00000000..29c507dc --- /dev/null +++ b/include/smtp/smtpclient.h @@ -0,0 +1,197 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef SMTPCLIENT_H +#define SMTPCLIENT_H + +#include <QObject> +#include <QtNetwork/QSslSocket> + +#include "mimemessage.h" +#include "smtpexports.h" + +class SMTP_EXPORT SmtpClient : public QObject { +Q_OBJECT +public: + + /* [0] Enumerations */ + + enum AuthMethod { + AuthPlain, + AuthLogin + }; + + enum SmtpError { + ConnectionTimeoutError, + ResponseTimeoutError, + SendDataTimeoutError, + AuthenticationFailedError, + ServerError, // 4xx smtp error + ClientError // 5xx smtp error + }; + + enum ConnectionType { + TcpConnection, + SslConnection, + TlsConnection // STARTTLS + }; + + /* [0] --- */ + + + /* [1] Constructors and Destructors */ + + explicit SmtpClient(const QString &host = "localhost", int port = 25, ConnectionType ct = TcpConnection); + + ~SmtpClient() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + [[nodiscard]] const QString &getHost() const; + + void setHost(const QString &host); + + [[nodiscard]] int getPort() const; + + void setPort(int port); + + [[nodiscard]] const QString &getName() const; + + void setName(const QString &name); + + [[nodiscard]] ConnectionType getConnectionType() const; + + void setConnectionType(ConnectionType ct); + + [[nodiscard]] const QString &getUser() const; + + void setUser(const QString &user); + + [[nodiscard]] const QString &getPassword() const; + + void setPassword(const QString &password); + + [[nodiscard]] SmtpClient::AuthMethod getAuthMethod() const; + + void setAuthMethod(AuthMethod method); + + [[nodiscard]] const QString &getResponseText() const; + + [[nodiscard]] int getResponseCode() const; + + [[nodiscard]] int getConnectionTimeout() const; + + void setConnectionTimeout(int msec); + + [[nodiscard]] int getResponseTimeout() const; + + void setResponseTimeout(int msec); + + [[nodiscard]] int getSendMessageTimeout() const; + + void setSendMessageTimeout(int msec); + + QTcpSocket *getSocket(); + + + /* [2] --- */ + + + /* [3] Public methods */ + + bool connectToHost(); + + bool login(); + + bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin); + + bool sendMail(MimeMessage &email); + + void quit(); + + + /* [3] --- */ + +protected: + + /* [4] Protected members */ + + QTcpSocket *socket; + + QString host; + int port; + ConnectionType connectionType; + QString name; + + QString user; + QString password; + AuthMethod authMethod; + + int connectionTimeout; + int responseTimeout; + int sendMessageTimeout; + + + QString responseText; + int responseCode; + + + class ResponseTimeoutException : public std::exception { + }; + + class SendMessageTimeoutException : public std::exception { + }; + + /* [4] --- */ + + + /* [5] Protected methods */ + + void waitForResponse(); + + void sendMessage(const QString &text); + + /* [5] --- */ + +protected slots: + + /* [6] Protected slots */ + + void socketStateChanged(QAbstractSocket::SocketState state); + + void socketError(QAbstractSocket::SocketError error); + + void socketReadyRead(); + + /* [6] --- */ + + +signals: + + /* [7] Signals */ + + void smtpError(SmtpClient::SmtpError e); + + /* [7] --- */ + +}; + +#endif // SMTPCLIENT_H diff --git a/include/smtp/smtpexports.h b/include/smtp/smtpexports.h new file mode 100644 index 00000000..9ca12bae --- /dev/null +++ b/include/smtp/smtpexports.h @@ -0,0 +1,10 @@ +#ifndef SMTPEXPORTS_H
+#define SMTPEXPORTS_H
+
+#ifdef SMTP_BUILD
+#define SMTP_EXPORT
+#else
+#define SMTP_EXPORT
+#endif
+
+#endif // SMTPEXPORTS_H
diff --git a/include/ui/AttachmentTableModel.h b/include/ui/AttachmentTableModel.h deleted file mode 100644 index 9bc22cea..00000000 --- a/include/ui/AttachmentTableModel.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar 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 General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#ifndef __ATTACHMENTTABLEMODEL_H__ -#define __ATTACHMENTTABLEMODEL_H__ - -#include "Mime.h" - -class AttachmentTableModel : public QAbstractTableModel { -Q_OBJECT - -public: - explicit AttachmentTableModel(QObject *parent = nullptr); - - explicit AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent = nullptr); - - int rowCount(const QModelIndex &parent) const override; - - int columnCount(const QModelIndex &parent) const override; - - [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; - - [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - - void add(const MimePart& mp); - - MimePart getSelectedMimePart(QModelIndex index); - - MimePart getMimePart(int index); - //QList<MimePart> getSelectedMimeParts(QModelIndexList indexes); - -private: - QList<MimePart> listOfMimeparts; -}; - -#endif // __ATTACHMENTTABLEMODEL_H__ diff --git a/include/ui/widgets/Attachments.h b/include/ui/widgets/Attachments.h deleted file mode 100644 index 00433028..00000000 --- a/include/ui/widgets/Attachments.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar 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 General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#ifndef __ATTACHMENTS_H__ -#define __ATTACHMENTS_H__ - -#include "ui/AttachmentTableModel.h" - -class Attachments : public QWidget { -Q_OBJECT - -public slots: - - void slotSaveFile(); - - void slotOpenFile(); - -public: - explicit Attachments(QWidget *parent = nullptr); - - void addMimePart(MimePart *mp); - -private: - void createActions(); - - void saveByteArrayToFile(QByteArray outBuffer, QString filename); - - QAction *saveFileAct{}; - QAction *openFileAct{}; - AttachmentTableModel *table; - QTableView *tableView; - QSettings settings; - -protected: - void contextMenuEvent(QContextMenuEvent *event) override; -}; - -#endif // __ATTACHMENTS_H__ diff --git a/resource/ts/gpg_frontend_fr.ts b/resource/ts/gpg_frontend_fr.ts index 92d8d1dc..8d5027fb 100644 --- a/resource/ts/gpg_frontend_fr.ts +++ b/resource/ts/gpg_frontend_fr.ts @@ -96,56 +96,6 @@ </message> </context> <context> - <name>AttachmentTableModel</name> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> <name>ChoosePage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="165"/> @@ -463,32 +413,32 @@ <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="580"/> + <location filename="../../src/gpg/GpgContext.cpp" line="525"/> <source>Wrong password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="588"/> + <location filename="../../src/gpg/GpgContext.cpp" line="533"/> <source>Enter Password for</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="592"/> + <location filename="../../src/gpg/GpgContext.cpp" line="537"/> <source>Enter Password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>Key Selection</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>No Private Key Selected</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="787"/> + <location filename="../../src/gpg/GpgContext.cpp" line="732"/> <source>Error in signing:</source> <translation type="unfinished"></translation> </message> @@ -2758,11 +2708,6 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <source>Information Board</source> <translation type="unfinished"></translation> </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="463"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>MimeTab</name> diff --git a/resource/ts/gpg_frontend_ru.ts b/resource/ts/gpg_frontend_ru.ts index d96c8778..f3dc9093 100644 --- a/resource/ts/gpg_frontend_ru.ts +++ b/resource/ts/gpg_frontend_ru.ts @@ -96,56 +96,6 @@ </message> </context> <context> - <name>AttachmentTableModel</name> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> <name>ChoosePage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="165"/> @@ -463,32 +413,32 @@ <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="580"/> + <location filename="../../src/gpg/GpgContext.cpp" line="525"/> <source>Wrong password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="588"/> + <location filename="../../src/gpg/GpgContext.cpp" line="533"/> <source>Enter Password for</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="592"/> + <location filename="../../src/gpg/GpgContext.cpp" line="537"/> <source>Enter Password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>Key Selection</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>No Private Key Selected</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="787"/> + <location filename="../../src/gpg/GpgContext.cpp" line="732"/> <source>Error in signing:</source> <translation type="unfinished"></translation> </message> @@ -2758,11 +2708,6 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <source>Information Board</source> <translation type="unfinished"></translation> </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="463"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>MimeTab</name> diff --git a/resource/ts/gpgfrontend_en_us.ts b/resource/ts/gpgfrontend_en_us.ts index d111ddf4..03dc57e3 100644 --- a/resource/ts/gpgfrontend_en_us.ts +++ b/resource/ts/gpgfrontend_en_us.ts @@ -96,56 +96,6 @@ </message> </context> <context> - <name>AttachmentTableModel</name> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> <name>ChoosePage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="165"/> @@ -463,32 +413,32 @@ <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="580"/> + <location filename="../../src/gpg/GpgContext.cpp" line="525"/> <source>Wrong password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="588"/> + <location filename="../../src/gpg/GpgContext.cpp" line="533"/> <source>Enter Password for</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="592"/> + <location filename="../../src/gpg/GpgContext.cpp" line="537"/> <source>Enter Password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>Key Selection</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>No Private Key Selected</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="787"/> + <location filename="../../src/gpg/GpgContext.cpp" line="732"/> <source>Error in signing:</source> <translation type="unfinished"></translation> </message> @@ -2758,11 +2708,6 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <source>Information Board</source> <translation type="unfinished"></translation> </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="463"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>MimeTab</name> diff --git a/resource/ts/gpgfrontend_zh_chs.ts b/resource/ts/gpgfrontend_zh_chs.ts index feeef9da..d4e036b2 100644 --- a/resource/ts/gpgfrontend_zh_chs.ts +++ b/resource/ts/gpgfrontend_zh_chs.ts @@ -96,56 +96,6 @@ </message> </context> <context> - <name>AttachmentTableModel</name> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> <name>ChoosePage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="165"/> @@ -463,32 +413,32 @@ <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="580"/> + <location filename="../../src/gpg/GpgContext.cpp" line="525"/> <source>Wrong password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="588"/> + <location filename="../../src/gpg/GpgContext.cpp" line="533"/> <source>Enter Password for</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="592"/> + <location filename="../../src/gpg/GpgContext.cpp" line="537"/> <source>Enter Password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>Key Selection</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>No Private Key Selected</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="787"/> + <location filename="../../src/gpg/GpgContext.cpp" line="732"/> <source>Error in signing:</source> <translation type="unfinished"></translation> </message> @@ -2758,11 +2708,6 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <source>Information Board</source> <translation type="unfinished"></translation> </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="463"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>MimeTab</name> diff --git a/resource/ts/gpgfrontend_zh_cht.ts b/resource/ts/gpgfrontend_zh_cht.ts index feeef9da..d4e036b2 100644 --- a/resource/ts/gpgfrontend_zh_cht.ts +++ b/resource/ts/gpgfrontend_zh_cht.ts @@ -96,56 +96,6 @@ </message> </context> <context> - <name>AttachmentTableModel</name> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> <name>ChoosePage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="165"/> @@ -463,32 +413,32 @@ <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="580"/> + <location filename="../../src/gpg/GpgContext.cpp" line="525"/> <source>Wrong password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="588"/> + <location filename="../../src/gpg/GpgContext.cpp" line="533"/> <source>Enter Password for</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="592"/> + <location filename="../../src/gpg/GpgContext.cpp" line="537"/> <source>Enter Password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>Key Selection</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="747"/> + <location filename="../../src/gpg/GpgContext.cpp" line="692"/> <source>No Private Key Selected</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="787"/> + <location filename="../../src/gpg/GpgContext.cpp" line="732"/> <source>Error in signing:</source> <translation type="unfinished"></translation> </message> @@ -2758,11 +2708,6 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <source>Information Board</source> <translation type="unfinished"></translation> </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="463"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>MimeTab</name> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 243570e5..03eaac9e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ set(ALL_SOURCE_FILE) add_subdirectory(gpg) add_subdirectory(ui) +add_subdirectory(smtp) aux_source_directory(. BASE_SOURCE) @@ -121,19 +122,19 @@ endif() IF (MINGW) message(STATUS "Link Application Static Library For MINGW") target_link_libraries(${AppName} - gpgfrontend-ui gpg + smtp gpgfrontend-ui gpg Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core crypto ssl) elseif(APPLE) message(STATUS "Link Application Static Library For macOS") target_link_libraries(${AppName} - gpgfrontend-ui gpg + smtp gpgfrontend-ui gpg Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core crypto ssl) else() message(STATUS "Link Application Static Library For UNIX") target_link_libraries(${AppName} - gpgfrontend-ui gpg + smtp gpgfrontend-ui gpg Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core crypto ssl pthread) endif() diff --git a/src/Mime.cpp b/src/Mime.cpp deleted file mode 100644 index 8e4c8d72..00000000 --- a/src/Mime.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar 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 General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -/* TODO: proper import / copyright statement - * - */ - -#include "Mime.h" - -Mime::Mime(QByteArray *message) { - splitParts(message); - /* - mMessage = message; - int bStart = mMessage->indexOf("boundary=\"") + 10 ; - int bEnd = mMessage->indexOf("\"\n", bStart ); - - qDebug() << "bStart: " << bStart << " bEnd: " << bEnd; - mBoundary = new QByteArray(mMessage->mid(bStart, bEnd - bStart)); - qDebug() << "boundary: " << *mBoundary; - - Part *p1 = new Part(); - - int nb = mMessage->indexOf(*mBoundary, bEnd) + mBoundary->length() +1 ; - qDebug() << "nb: " << nb; - int eh = mMessage->indexOf("\n\n", nb); - qDebug() << "eh: " << eh; - QByteArray *header = new QByteArray(mMessage->mid(nb , eh - nb)); - qDebug() << "header:" << header; - - // split header at newlines - foreach(QByteArray tmp , header->split(* "\n")) { - // split lines at : - QList<QByteArray> tmp2 = tmp.split(* ":"); - p1->header.insert(QString(tmp2[0].trimmed()), QString(tmp2[1].trimmed())); - } - - QHashIterator<QString, QString> i(p1->header); - while (i.hasNext()) { - i.next(); - qDebug() << "found: " << i.key() << ":" << i.value() << endl; - } - - int nb2 = mMessage->indexOf(*mBoundary, eh); - - p1->body = mMessage->mid(eh , nb2 - eh); - - QTextCodec *codec = QTextCodec::codecForName("ISO-8859-15"); - QString qs = codec->toUnicode(p1->body); - qDebug() << "body: " << qs; - */ -} - -Mime::~Mime() -= default; - -void Mime::splitParts(QByteArray *message) { - int pos1, pos2, headEnd; - MimePart p_tmp; - - // find the boundary - pos1 = message->indexOf("boundary=\"") + 10; - pos2 = message->indexOf("\"\n", pos1); - QByteArray boundary = message->mid(pos1, pos2 - pos1); - //qDebug() << "boundary: " << boundary; - - while (pos2 > pos1) { - - pos1 = message->indexOf(boundary, pos2) + boundary.length() + 1; - headEnd = message->indexOf("\n\n", pos1); - if (headEnd < 0) - break; - QByteArray header = message->mid(pos1, headEnd - pos1); - - p_tmp.header = parseHeader(&header); - - pos2 = message->indexOf(boundary, headEnd); - p_tmp.body = message->mid(headEnd, pos2 - headEnd); - - mPartList.append(p_tmp); - } -} - -Header Mime::parseHeader(QByteArray *header) { - - QList<HeadElem> ret; - - /** http://www.aspnetmime.com/help/welcome/overviewmimeii.html : - * If a line starts with any white space, that line is said to be 'folded' and is actually - * part of the header above it. - */ - header->replace("\n ", " "); - - //split header at newlines - foreach(QByteArray line, header->split(*"\n")) { - HeadElem elem; - //split lines at : - QList<QByteArray> tmp2 = line.split(*":"); - elem.name = tmp2[0].trimmed(); - if (tmp2[1].contains(';')) { - // split lines at ; - // TODO: what if ; is inside "" - QList<QByteArray> tmp3 = tmp2[1].split(*";"); - elem.value = QString(tmp3.takeFirst().trimmed()); - foreach(QByteArray tmp4, tmp3) { - QList<QByteArray> tmp5 = tmp4.split(*"="); - elem.params.insert(QString(tmp5[0].trimmed()), QString(tmp5[1].trimmed())); - } - } else { - elem.value = tmp2[1].trimmed(); - } - ret.append(elem); - } - return Header(ret); -} - -Header Mime::getHeader(const QByteArray *message) { - int headEnd = message->indexOf("\n\n"); - QByteArray header = message->mid(0, headEnd); - return parseHeader(&header); -} - -bool Mime::isMultipart(QByteArray *message) { - return message->startsWith("Content-Type: multipart/mixed;"); -} - -/** - * if Content-Type is specified, it should be mime - * - */ -bool Mime::isMime(const QByteArray *message) { - return message->startsWith("Content-Type:"); -} - -/*** - * quotedPrintableDecode copied from KCodecs, where it is stated: - - The quoted-printable codec as described in RFC 2045, section 6.7. is by - Rik Hemsley (C) 2001. - - */ - -static const char hexChars[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/******************************** KCodecs ********************************/ -// strchr(3) for broken systems. -static int rikFindChar(const char *_s, const char c) { - const char *s = _s; - - while (true) { - if ((0 == *s) || (c == *s)) break; - ++s; - if ((0 == *s) || (c == *s)) break; - ++s; - if ((0 == *s) || (c == *s)) break; - ++s; - if ((0 == *s) || (c == *s)) break; - ++s; - } - - return static_cast<int>(s - _s); -} - -void Mime::quotedPrintableDecode(const QByteArray &in, QByteArray &out) { - // clear out the output buffer - out.resize(0); - if (in.isEmpty()) - return; - - char *cursor; - const char *data; - const size_t length = in.size(); - - data = in.data(); - out.resize(static_cast<int>(length)); - cursor = out.data(); - - for (unsigned int i = 0; i < length; i++) { - char c(in[i]); - - if ('=' == c) { - if (i < length - 2) { - char c1 = in[i + 1]; - char c2 = in[i + 2]; - - if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) { - // Soft line break. No output. - if ('\r' == c1) - i += 2; // CRLF line breaks - else - i += 1; - } else { - // =XX encoded byte. - - int hexChar0 = rikFindChar(hexChars, c1); - int hexChar1 = rikFindChar(hexChars, c2); - - if (hexChar0 < 16 && hexChar1 < 16) { - *cursor++ = char((hexChar0 * 16) | hexChar1); - i += 2; - } - } - } - } else { - *cursor++ = c; - } - } - - out.truncate(static_cast<int>(cursor - out.data())); -} diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index 028653b7..7ec521a7 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -25,7 +25,6 @@ #include "gpg/GpgContext.h" #include <unistd.h> /* contains read/write */ -#include <Mime.h> #ifdef _WIN32 @@ -430,38 +429,6 @@ namespace GpgME { return err; } - - /** - * if this is mime, split text and attachments... - * message contains only text afterwards - */ - void parseMime(QByteArray *message) { - - QString pText; - bool show_ma_dock = false; - - Mime *mime = new Mime(message); - for (MimePart tmp : mime->parts()) { - if (tmp.header.getValue("Content-Type") == "text/plain" && - tmp.header.getValue("Content-Transfer-Encoding") != "base64") { - QByteArray body; - if (tmp.header.getValue("Content-Transfer-Encoding") == "quoted-printable") { - Mime::quotedPrintableDecode(tmp.body, body); - } else { - body = tmp.body; - } - pText.append(QString(body)); - } else { - // TODO - show_ma_dock = true; - } - } - *message = pText.toUtf8(); - if (show_ma_dock) { - // TODO - } - } - /** Decrypt QByteAarray, return QByteArray * mainly from http://basket.kde.org/ (kgpgme.cpp) */ @@ -496,28 +463,6 @@ namespace GpgME { gpgme_data_release(dataOut); } - /* - * 1) is it mime (content-type:) - * 2) parse header - * 2) choose action depending on content-type - */ - if (Mime::isMime(outBuffer)) { - Header header = Mime::getHeader(outBuffer); - // is it multipart, is multipart-parsing enabled - if (header.getValue("Content-Type") == "multipart/mixed" - && settings.value("mime/parseMime").toBool()) { - parseMime(outBuffer); - } else if (header.getValue("Content-Type") == "text/plain" - && settings.value("mime/parseQP").toBool()) { - if (header.getValue("Content-Transfer-Encoding") == "quoted-printable") { - auto *decoded = new QByteArray(); - Mime::quotedPrintableDecode(*outBuffer, *decoded); - //TODO: remove header - outBuffer = decoded; - } - } - } - if (result != nullptr) { *result = m_result; } diff --git a/src/smtp/CMakeLists.txt b/src/smtp/CMakeLists.txt new file mode 100644 index 00000000..8e341f98 --- /dev/null +++ b/src/smtp/CMakeLists.txt @@ -0,0 +1,6 @@ +aux_source_directory(. SMTP_MIME_SOURCE) + +add_library(smtp STATIC ${SMTP_MIME_SOURCE}) + +target_link_libraries(smtp + Qt5::Network Qt5::Core) diff --git a/src/smtp/emailaddress.cpp b/src/smtp/emailaddress.cpp new file mode 100644 index 00000000..c0ecaa0d --- /dev/null +++ b/src/smtp/emailaddress.cpp @@ -0,0 +1,44 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/emailaddress.h" + +/* [1] Constructors and Destructors */ + +EmailAddress::EmailAddress(const QString &address, const QString &name) { + this->address = address; + this->name = name; +} + +EmailAddress::~EmailAddress() {} + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void EmailAddress::setName(const QString &name) { this->name = name; } + +void EmailAddress::setAddress(const QString &address) { + this->address = address; +} + +const QString &EmailAddress::getName() const { return name; } + +const QString &EmailAddress::getAddress() const { return address; } + +/* [2] --- */ diff --git a/src/smtp/mimeattachment.cpp b/src/smtp/mimeattachment.cpp new file mode 100644 index 00000000..033eecfb --- /dev/null +++ b/src/smtp/mimeattachment.cpp @@ -0,0 +1,43 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimeattachment.h" +#include <QFileInfo> + +/* [1] Constructors and Destructors */ + +MimeAttachment::MimeAttachment(QFile *file) : MimeFile(file) {} + +MimeAttachment::MimeAttachment(const QByteArray &stream, + const QString &fileName) + : MimeFile(stream, fileName) {} + +MimeAttachment::~MimeAttachment() = default; + +/* [1] --- */ + +/* [2] Protected methods */ + +void MimeAttachment::prepare() { + this->header += "Content-disposition: attachment\r\n"; + + /* !!! IMPORTANT !!! */ + MimeFile::prepare(); +} + +/* [2] --- */ diff --git a/src/smtp/mimecontentformatter.cpp b/src/smtp/mimecontentformatter.cpp new file mode 100644 index 00000000..8f538457 --- /dev/null +++ b/src/smtp/mimecontentformatter.cpp @@ -0,0 +1,59 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimecontentformatter.h" + +MimeContentFormatter::MimeContentFormatter(int max_length) + : max_length(max_length) {} + +QString MimeContentFormatter::format(const QString &content, + bool quotedPrintable) const { + + QString out; + + int chars = 0; + for (auto i : content) { + chars++; + if (!quotedPrintable) { + if (chars > max_length) { + out.append("\r\n"); + chars = 1; + } + } else { + if (i == '\n') { // new line + out.append(i); + chars = 0; + continue; + } + + if ((chars > max_length - 1) || + ((i == '=') && (chars > max_length - 3))) { + out.append('='); + out.append("\r\n"); + chars = 1; + } + } + out.append(i); + } + + return out; +} + +void MimeContentFormatter::setMaxLength(int l) { max_length = l; } + +int MimeContentFormatter::getMaxLength() const { return max_length; } diff --git a/src/smtp/mimefile.cpp b/src/smtp/mimefile.cpp new file mode 100644 index 00000000..4f095b84 --- /dev/null +++ b/src/smtp/mimefile.cpp @@ -0,0 +1,61 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimefile.h" +#include <QFileInfo> + +/* [1] Constructors and Destructors */ + +MimeFile::MimeFile(QFile *file) { + this->file = file; + this->cType = "application/octet-stream"; + this->cName = QFileInfo(*file).fileName(); + this->cEncoding = Base64; +} + +MimeFile::MimeFile(const QByteArray &stream, const QString &fileName) { + this->cEncoding = Base64; + this->cType = "application/octet-stream"; + this->file = nullptr; + this->cName = fileName; + this->content = stream; +} + +MimeFile::~MimeFile() { + delete file; +} + +/* [1] --- */ + +/* [2] Getters and setters */ + +/* [2] --- */ + +/* [3] Protected methods */ + +void MimeFile::prepare() { + if (this->file) { + file->open(QIODevice::ReadOnly); + this->content = file->readAll(); + file->close(); + } + /* !!! IMPORTANT !!!! */ + MimePart::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/mimehtml.cpp b/src/smtp/mimehtml.cpp new file mode 100644 index 00000000..9f3a53c3 --- /dev/null +++ b/src/smtp/mimehtml.cpp @@ -0,0 +1,46 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimehtml.h" + +/* [1] Constructors and Destructors */ + +MimeHtml::MimeHtml(const QString &html) : MimeText(html) { + this->cType = "text/html"; +} + +MimeHtml::~MimeHtml() = default; + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void MimeHtml::setHtml(const QString &html) { this->text = html; } + +const QString &MimeHtml::getHtml() const { return text; } + +/* [2] --- */ + +/* [3] Protected methods */ + +void MimeHtml::prepare() { + /* !!! IMPORTANT !!! */ + MimeText::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/mimeinlinefile.cpp b/src/smtp/mimeinlinefile.cpp new file mode 100644 index 00000000..a49167e8 --- /dev/null +++ b/src/smtp/mimeinlinefile.cpp @@ -0,0 +1,42 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimeinlinefile.h" + +/* [1] Constructors and Destructors */ + +MimeInlineFile::MimeInlineFile(QFile *f) : MimeFile(f) {} + +MimeInlineFile::~MimeInlineFile() = default; + +/* [1] --- */ + +/* [2] Getters and Setters */ + +/* [2] --- */ + +/* [3] Protected methods */ + +void MimeInlineFile::prepare() { + this->header += "Content-Disposition: inline\r\n"; + + /* !!! IMPORTANT !!! */ + MimeFile::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/mimemessage.cpp b/src/smtp/mimemessage.cpp new file mode 100644 index 00000000..cf653e0a --- /dev/null +++ b/src/smtp/mimemessage.cpp @@ -0,0 +1,308 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimemessage.h" +#include "smtp/quotedprintable.h" + +#include <QDateTime> +#include <QLocale> +#include <typeinfo> + +/* [1] Constructors and Destructors */ +MimeMessage::MimeMessage(bool createAutoMimeContent) + : replyTo(nullptr), hEncoding(MimePart::_8Bit) { + if (createAutoMimeContent) + this->content = new MimeMultiPart(); + + autoMimeContentCreated = createAutoMimeContent; +} + +MimeMessage::~MimeMessage() { + if (this->autoMimeContentCreated) { + this->autoMimeContentCreated = false; + delete (this->content); + } +} + +/* [1] --- */ + +/* [2] Getters and Setters */ +MimePart &MimeMessage::getContent() { return *content; } + +void MimeMessage::setContent(MimePart *content) { + if (this->autoMimeContentCreated) { + this->autoMimeContentCreated = false; + delete (this->content); + } + this->content = content; +} + +void MimeMessage::setReplyTo(EmailAddress *rto) { replyTo = rto; } + +void MimeMessage::setSender(EmailAddress *e) { + this->sender = e; + e->setParent(this); +} + +void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type) { + switch (type) { + case To: + recipientsTo << rcpt; + break; + case Cc: + recipientsCc << rcpt; + break; + case Bcc: + recipientsBcc << rcpt; + break; + } + + rcpt->setParent(this); +} + +void MimeMessage::addTo(EmailAddress *rcpt) { this->recipientsTo << rcpt; } + +void MimeMessage::addCc(EmailAddress *rcpt) { this->recipientsCc << rcpt; } + +void MimeMessage::addBcc(EmailAddress *rcpt) { this->recipientsBcc << rcpt; } + +void MimeMessage::setSubject(const QString &subject) { + this->subject = subject; +} + +void MimeMessage::addPart(MimePart *part) { + if (typeid(*content) == typeid(MimeMultiPart)) { + ((MimeMultiPart *) content)->addPart(part); + }; +} + +void MimeMessage::setInReplyTo(const QString &inReplyTo) { + mInReplyTo = inReplyTo; +} + +void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc) { + this->hEncoding = hEnc; +} + +const EmailAddress &MimeMessage::getSender() const { return *sender; } + +const QList<EmailAddress *> & +MimeMessage::getRecipients(RecipientType type) const { + switch (type) { + default: + case To: + return recipientsTo; + case Cc: + return recipientsCc; + case Bcc: + return recipientsBcc; + } +} + +const EmailAddress *MimeMessage::getReplyTo() const { return replyTo; } + +const QString &MimeMessage::getSubject() const { return subject; } + +const QList<MimePart *> &MimeMessage::getParts() const { + if (typeid(*content) == typeid(MimeMultiPart)) { + return ((MimeMultiPart *) content)->getParts(); + } else { + auto *res = new QList<MimePart *>(); + res->append(content); + return *res; + } +} + +/* [2] --- */ + +/* [3] Public Methods */ + +QString MimeMessage::toString() { + QString mime; + + /* =========== MIME HEADER ============ */ + + /* ---------- Sender / From ----------- */ + mime = "From:"; + if (sender->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append(sender->getName().toUtf8()).toBase64() + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode( + QByteArray().append(sender->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + sender->getName(); + } + } + mime += " <" + sender->getAddress() + ">\r\n"; + /* ---------------------------------- */ + + /* ------- Recipients / To ---------- */ + mime += "To:"; + QList<EmailAddress *>::iterator it; + int i; + for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) { + if (i != 0) { + mime += ","; + } + + if ((*it)->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append((*it)->getName().toUtf8()).toBase64() + + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode( + QByteArray().append((*it)->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + (*it)->getName(); + } + } + mime += " <" + (*it)->getAddress() + ">"; + } + mime += "\r\n"; + /* ---------------------------------- */ + + /* ------- Recipients / Cc ---------- */ + if (!recipientsCc.empty()) { + mime += "Cc:"; + } + for (i = 0, it = recipientsCc.begin(); it != recipientsCc.end(); ++it, ++i) { + if (i != 0) { + mime += ","; + } + + if ((*it)->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append((*it)->getName().toUtf8()).toBase64() + + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode( + QByteArray().append((*it)->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + (*it)->getName(); + } + } + mime += " <" + (*it)->getAddress() + ">"; + } + if (!recipientsCc.empty()) { + mime += "\r\n"; + } + /* ---------------------------------- */ + + /* ------------ Subject ------------- */ + mime += "Subject: "; + + switch (hEncoding) { + case MimePart::Base64: + mime += "=?utf-8?B?" + QByteArray().append(subject.toUtf8()).toBase64() + "?="; + break; + case MimePart::QuotedPrintable: + mime += "=?utf-8?Q?" + + QuotedPrintable::encode(QByteArray().append(subject.toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += subject; + } + mime += "\r\n"; + /* ---------------------------------- */ + + /* ---------- Reply-To -------------- */ + if (replyTo) { + mime += "Reply-To: "; + if (replyTo->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append(replyTo->getName().toUtf8()).toBase64() + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode(QByteArray().append(replyTo->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + replyTo->getName(); + } + } + mime += " <" + replyTo->getAddress() + ">\r\n"; + } + + /* ---------------------------------- */ + + mime += "MIME-Version: 1.0\r\n"; + if (!mInReplyTo.isEmpty()) { + mime += "In-Reply-To: <" + mInReplyTo + ">\r\n"; + mime += "References: <" + mInReplyTo + ">\r\n"; + } + + QDateTime now = QDateTime::currentDateTime(); +#if QT_VERSION_MAJOR < 5 // Qt4 workaround since RFC2822Date isn't defined + QString shortDayName = + QLocale::c().dayName(now.date().dayOfWeek(), QLocale::ShortFormat); + QString shortMonthName = + QLocale::c().monthName(now.date().month(), QLocale::ShortFormat); + int utcOffset = now.secsTo(QDateTime(now.date(), now.time(), Qt::UTC)) / 60; + char timezoneSign = utcOffset >= 0 ? '+' : '-'; + utcOffset = utcOffset >= 0 ? utcOffset : -utcOffset; + QString timezone = QString("%1%2%3") + .arg(timezoneSign) + .arg(utcOffset / 60, 2, 10, QChar('0')) + .arg(utcOffset % 60, 2, 10, QChar('0')); + mime += QString("Date: %1\r\n") + .arg(now.toString("%1, dd %2 yyyy hh:mm:ss %3") + .arg(shortDayName) + .arg(shortMonthName) + .arg(timezone)); +#else // Qt5 supported + mime += QString("Date: %1\r\n").arg(now.toString(Qt::RFC2822Date)); +#endif // support RFC2822Date + + mime += content->toString(); + return mime; +} + +/* [3] --- */ diff --git a/src/smtp/mimemultipart.cpp b/src/smtp/mimemultipart.cpp new file mode 100644 index 00000000..14a813c2 --- /dev/null +++ b/src/smtp/mimemultipart.cpp @@ -0,0 +1,70 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimemultipart.h" +#include <QCryptographicHash> +#include <QRandomGenerator> +#include <QTime> + +const QString MULTI_PART_NAMES[] = { + "multipart/mixed", // Mixed + "multipart/digest", // Digest + "multipart/alternative", // Alternative + "multipart/related", // Related + "multipart/report", // Report + "multipart/signed", // Signed + "multipart/encrypted" // Encrypted +}; + +MimeMultiPart::MimeMultiPart(MultiPartType type) { + this->type = type; + this->cType = MULTI_PART_NAMES[this->type]; + this->cEncoding = _8Bit; + + QRandomGenerator generator; + + QCryptographicHash md5(QCryptographicHash::Md5); + md5.addData(QByteArray().append((char) generator.generate())); + cBoundary = md5.result().toHex(); +} + +void MimeMultiPart::addPart(MimePart *part) { parts.append(part); } + +const QList<MimePart *> &MimeMultiPart::getParts() const { return parts; } + +void MimeMultiPart::prepare() { + QList<MimePart *>::iterator it; + + content = ""; + for (it = parts.begin(); it != parts.end(); it++) { + content += QString("--" + cBoundary + "\r\n").toUtf8(); + (*it)->prepare(); + content += (*it)->toString().toUtf8(); + }; + + content += QString("--" + cBoundary + "--\r\n").toUtf8(); + + MimePart::prepare(); +} + +void MimeMultiPart::setMimeType(const MultiPartType type) { + this->type = type; + this->cType = MULTI_PART_NAMES[type]; +} + +MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const { return type; } diff --git a/src/smtp/mimepart.cpp b/src/smtp/mimepart.cpp new file mode 100644 index 00000000..5d33884d --- /dev/null +++ b/src/smtp/mimepart.cpp @@ -0,0 +1,159 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimepart.h" +#include "smtp/quotedprintable.h" + +/* [1] Constructors and Destructors */ + +MimePart::MimePart() { + cEncoding = _7Bit; + prepared = false; + cBoundary = ""; +} + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void MimePart::setContent(const QByteArray &content) { + this->content = content; +} + +void MimePart::setHeader(const QString &header) { this->header = header; } + +void MimePart::addHeaderLine(const QString &line) { + this->header += line + "\r\n"; +} + +const QString &MimePart::getHeader() const { return header; } + +const QByteArray &MimePart::getContent() const { return content; } + +void MimePart::setContentId(const QString &cId) { this->cId = cId; } + +const QString &MimePart::getContentId() const { return this->cId; } + +void MimePart::setContentName(const QString &cName) { this->cName = cName; } + +const QString &MimePart::getContentName() const { return this->cName; } + +void MimePart::setContentType(const QString &cType) { this->cType = cType; } + +const QString &MimePart::getContentType() const { return this->cType; } + +void MimePart::setCharset(const QString &charset) { this->cCharset = charset; } + +const QString &MimePart::getCharset() const { return this->cCharset; } + +void MimePart::setEncoding(Encoding enc) { this->cEncoding = enc; } + +MimePart::Encoding MimePart::getEncoding() const { return this->cEncoding; } + +MimeContentFormatter &MimePart::getContentFormatter() { + return this->formatter; +} + +/* [2] --- */ + +/* [3] Public methods */ + +QString MimePart::toString() { + if (!prepared) + prepare(); + + return mimeString; +} + +/* [3] --- */ + +/* [4] Protected methods */ + +void MimePart::prepare() { + mimeString = QString(); + + /* === Header Prepare === */ + + /* Content-Type */ + mimeString.append("Content-Type: ").append(cType); + + if (cName != "") + mimeString.append("; name=\"").append(cName).append("\""); + + if (cCharset != "") + mimeString.append("; charset=").append(cCharset); + + if (cBoundary != "") + mimeString.append("; boundary=").append(cBoundary); + + mimeString.append("\r\n"); + /* ------------ */ + + /* Content-Transfer-Encoding */ + mimeString.append("Content-Transfer-Encoding: "); + switch (cEncoding) { + case _7Bit: + mimeString.append("7bit\r\n"); + break; + case _8Bit: + mimeString.append("8bit\r\n"); + break; + case Base64: + mimeString.append("base64\r\n"); + break; + case QuotedPrintable: + mimeString.append("quoted-printable\r\n"); + break; + } + /* ------------------------ */ + + /* Content-Id */ + if (cId != NULL) + mimeString.append("Content-ID: <").append(cId).append(">\r\n"); + /* ---------- */ + + /* Addition header lines */ + + mimeString.append(header).append("\r\n"); + + /* ------------------------- */ + + /* === End of Header Prepare === */ + + /* === Content === */ + switch (cEncoding) { + case _7Bit: + mimeString.append(QString(content).toLatin1()); + break; + case _8Bit: + mimeString.append(content); + break; + case Base64: + mimeString.append(formatter.format(content.toBase64())); + break; + case QuotedPrintable: + mimeString.append(formatter.format(QuotedPrintable::encode(content), true)); + break; + } + mimeString.append("\r\n"); + /* === End of Content === */ + + prepared = true; +} + +/* [4] --- */ diff --git a/src/smtp/mimetext.cpp b/src/smtp/mimetext.cpp new file mode 100644 index 00000000..3726647e --- /dev/null +++ b/src/smtp/mimetext.cpp @@ -0,0 +1,52 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimetext.h" + +/* [1] Constructors and Destructors */ + +MimeText::MimeText(const QString &txt) { + this->text = txt; + this->cType = "text/plain"; + this->cCharset = "utf-8"; + this->cEncoding = _8Bit; +} + +MimeText::~MimeText() = default; + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void MimeText::setText(const QString &text) { this->text = text; } + +const QString &MimeText::getText() const { return text; } + +/* [2] --- */ + +/* [3] Protected Methods */ + +void MimeText::prepare() { + this->content.clear(); + this->content.append(text.toUtf8()); + + /* !!! IMPORTANT !!! */ + MimePart::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/quotedprintable.cpp b/src/smtp/quotedprintable.cpp new file mode 100644 index 00000000..93e51122 --- /dev/null +++ b/src/smtp/quotedprintable.cpp @@ -0,0 +1,62 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/quotedprintable.h" + +QString QuotedPrintable::encode(const QByteArray &input) { + QString output; + + char byte; + const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + for (char i : input) { + byte = i; + + if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) { + output.append(byte); + } else { + output.append('='); + output.append(hex[((byte >> 4) & 0x0F)]); + output.append(hex[(byte & 0x0F)]); + } + } + + return output; +} + +QByteArray QuotedPrintable::decode(const QString &input) { + // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B + // C D E F + const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, + 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15}; + + QByteArray output; + + for (int i = 0; i < input.length(); ++i) { + if (input.at(i).toLatin1() == '=') { + output.append((hexVal[input.at(i + 1).toLatin1() - '0'] << 4) + + hexVal[input.at(i + 2).toLatin1() - '0']); + i += 2; + } else { + output.append(input.at(i).toLatin1()); + } + } + + return output; +} diff --git a/src/smtp/smtpclient.cpp b/src/smtp/smtpclient.cpp new file mode 100644 index 00000000..63202998 --- /dev/null +++ b/src/smtp/smtpclient.cpp @@ -0,0 +1,407 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/smtpclient.h" + +#include <QByteArray> +#include <QFileInfo> + +/* [1] Constructors and destructors */ + +SmtpClient::SmtpClient(const QString &host, int port, + ConnectionType connectionType) + : socket(NULL), name("localhost"), authMethod(AuthPlain), + connectionTimeout(5000), responseTimeout(5000), + sendMessageTimeout(60000) { + setConnectionType(connectionType); + + this->host = host; + this->port = port; + + connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, + SLOT(socketStateChanged(QAbstractSocket::SocketState))); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, + SLOT(socketError(QAbstractSocket::SocketError))); + connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); +} + +SmtpClient::~SmtpClient() { + if (socket) + delete socket; +} + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void SmtpClient::setUser(const QString &user) { this->user = user; } + +void SmtpClient::setPassword(const QString &password) { + this->password = password; +} + +void SmtpClient::setAuthMethod(AuthMethod method) { this->authMethod = method; } + +void SmtpClient::setHost(const QString &host) { this->host = host; } + +void SmtpClient::setPort(int port) { this->port = port; } + +void SmtpClient::setConnectionType(ConnectionType ct) { + this->connectionType = ct; + + if (socket) + delete socket; + + switch (connectionType) { + case TcpConnection: + socket = new QTcpSocket(this); + break; + case SslConnection: + case TlsConnection: + socket = new QSslSocket(this); + } +} + +const QString &SmtpClient::getHost() const { return this->host; } + +const QString &SmtpClient::getUser() const { return this->user; } + +const QString &SmtpClient::getPassword() const { return this->password; } + +SmtpClient::AuthMethod SmtpClient::getAuthMethod() const { + return this->authMethod; +} + +int SmtpClient::getPort() const { return this->port; } + +SmtpClient::ConnectionType SmtpClient::getConnectionType() const { + return connectionType; +} + +const QString &SmtpClient::getName() const { return this->name; } + +void SmtpClient::setName(const QString &name) { this->name = name; } + +const QString &SmtpClient::getResponseText() const { return responseText; } + +int SmtpClient::getResponseCode() const { return responseCode; } + +QTcpSocket *SmtpClient::getSocket() { return socket; } + +int SmtpClient::getConnectionTimeout() const { return connectionTimeout; } + +void SmtpClient::setConnectionTimeout(int msec) { connectionTimeout = msec; } + +int SmtpClient::getResponseTimeout() const { return responseTimeout; } + +void SmtpClient::setResponseTimeout(int msec) { responseTimeout = msec; } + +int SmtpClient::getSendMessageTimeout() const { return sendMessageTimeout; } + +void SmtpClient::setSendMessageTimeout(int msec) { sendMessageTimeout = msec; } + +/* [2] --- */ + +/* [3] Public methods */ + +bool SmtpClient::connectToHost() { + switch (connectionType) { + case TlsConnection: + case TcpConnection: + socket->connectToHost(host, port); + break; + case SslConnection: + ((QSslSocket *) socket)->connectToHostEncrypted(host, port); + break; + } + + // Tries to connect to server + if (!socket->waitForConnected(connectionTimeout)) { + emit smtpError(ConnectionTimeoutError); + return false; + } + + try { + // Wait for the server's response + waitForResponse(); + + // If the response code is not 220 (Service ready) + // means that is something wrong with the server + if (responseCode != 220) { + emit smtpError(ServerError); + return false; + } + + // Send a EHLO/HELO message to the server + // The client's first command must be EHLO/HELO + sendMessage("EHLO " + name); + + // Wait for the server's response + waitForResponse(); + + // The response code needs to be 250. + if (responseCode != 250) { + emit smtpError(ServerError); + return false; + } + + if (connectionType == TlsConnection) { + // send a request to start TLS handshake + sendMessage("STARTTLS"); + + // Wait for the server's response + waitForResponse(); + + // The response code needs to be 220. + if (responseCode != 220) { + emit smtpError(ServerError); + return false; + }; + + ((QSslSocket *) socket)->startClientEncryption(); + + if (!((QSslSocket *) socket)->waitForEncrypted(connectionTimeout)) { + qDebug() << ((QSslSocket *) socket)->errorString(); + emit smtpError(ConnectionTimeoutError); + return false; + } + + // Send ELHO one more time + sendMessage("EHLO " + name); + + // Wait for the server's response + waitForResponse(); + + // The response code needs to be 250. + if (responseCode != 250) { + emit smtpError(ServerError); + return false; + } + } + } catch (ResponseTimeoutException) { + return false; + } catch (SendMessageTimeoutException) { + return false; + } + + // If no errors occured the function returns true. + return true; +} + +bool SmtpClient::login() { return login(user, password, authMethod); } + +bool SmtpClient::login(const QString &user, const QString &password, + AuthMethod method) { + try { + if (method == AuthPlain) { + // Sending command: AUTH PLAIN base64('\0' + username + '\0' + password) + sendMessage("AUTH PLAIN " + QByteArray() + .append((char) 0) + .append(user.toUtf8()) + .append((char) 0) + .append(password.toUtf8()) + .toBase64()); + + // Wait for the server's response + waitForResponse(); + + // If the response is not 235 then the authentication was faild + if (responseCode != 235) { + emit smtpError(AuthenticationFailedError); + return false; + } + } else if (method == AuthLogin) { + // Sending command: AUTH LOGIN + sendMessage("AUTH LOGIN"); + + // Wait for 334 response code + waitForResponse(); + if (responseCode != 334) { + emit smtpError(AuthenticationFailedError); + return false; + } + + // Send the username in base64 + sendMessage(QByteArray().append(user.toUtf8()).toBase64()); + + // Wait for 334 + waitForResponse(); + if (responseCode != 334) { + emit smtpError(AuthenticationFailedError); + return false; + } + + // Send the password in base64 + sendMessage(QByteArray().append(password.toUtf8()).toBase64()); + + // Wait for the server's responce + waitForResponse(); + + // If the response is not 235 then the authentication was faild + if (responseCode != 235) { + emit smtpError(AuthenticationFailedError); + return false; + } + } + } catch (ResponseTimeoutException) { + // Responce Timeout exceeded + emit smtpError(AuthenticationFailedError); + return false; + } catch (SendMessageTimeoutException) { + // Send Timeout exceeded + emit smtpError(AuthenticationFailedError); + return false; + } + + return true; +} + +bool SmtpClient::sendMail(MimeMessage &email) { + try { + // Send the MAIL command with the sender + sendMessage("MAIL FROM:<" + email.getSender().getAddress() + ">"); + + waitForResponse(); + + if (responseCode != 250) + return false; + + // Send RCPT command for each recipient + QList<EmailAddress *>::const_iterator it, itEnd; + // To (primary recipients) + for (it = email.getRecipients().begin(), + itEnd = email.getRecipients().end(); + it != itEnd; ++it) { + + sendMessage("RCPT TO:<" + (*it)->getAddress() + ">"); + waitForResponse(); + + if (responseCode != 250) + return false; + } + + // Cc (carbon copy) + for (it = email.getRecipients(MimeMessage::Cc).begin(), + itEnd = email.getRecipients(MimeMessage::Cc).end(); + it != itEnd; ++it) { + sendMessage("RCPT TO:<" + (*it)->getAddress() + ">"); + waitForResponse(); + + if (responseCode != 250) + return false; + } + + // Bcc (blind carbon copy) + for (it = email.getRecipients(MimeMessage::Bcc).begin(), + itEnd = email.getRecipients(MimeMessage::Bcc).end(); + it != itEnd; ++it) { + sendMessage("RCPT TO:<" + (*it)->getAddress() + ">"); + waitForResponse(); + + if (responseCode != 250) + return false; + } + + // Send DATA command + sendMessage("DATA"); + waitForResponse(); + + if (responseCode != 354) + return false; + + sendMessage(email.toString()); + + // Send \r\n.\r\n to end the mail data + sendMessage("."); + + waitForResponse(); + + if (responseCode != 250) + return false; + } catch (ResponseTimeoutException) { + return false; + } catch (SendMessageTimeoutException) { + return false; + } + + return true; +} + +void SmtpClient::quit() { + try { + sendMessage("QUIT"); + } catch (SmtpClient::SendMessageTimeoutException) { + // Manually close the connection to the smtp server if message "QUIT" wasn't + // received by the smtp server + if (socket->state() == QAbstractSocket::ConnectedState || + socket->state() == QAbstractSocket::ConnectingState || + socket->state() == QAbstractSocket::HostLookupState) + socket->disconnectFromHost(); + } +} + +/* [3] --- */ + +/* [4] Protected methods */ + +void SmtpClient::waitForResponse() { + do { + if (!socket->waitForReadyRead(responseTimeout)) { + emit smtpError(ResponseTimeoutError); + throw ResponseTimeoutException(); + } + + while (socket->canReadLine()) { + // Save the server's response + responseText = socket->readLine(); + + // Extract the respose code from the server's responce (first 3 digits) + responseCode = responseText.leftRef(3).toInt(); + + if (responseCode / 100 == 4) + emit smtpError(ServerError); + + if (responseCode / 100 == 5) + emit smtpError(ClientError); + + if (responseText[3] == ' ') { + return; + } + } + } while (true); +} + +void SmtpClient::sendMessage(const QString &text) { + socket->write(text.toUtf8() + "\r\n"); + if (!socket->waitForBytesWritten(sendMessageTimeout)) { + emit smtpError(SendDataTimeoutError); + throw SendMessageTimeoutException(); + } +} + +/* [4] --- */ + +/* [5] Slots for the socket's signals */ + +void SmtpClient::socketStateChanged(QAbstractSocket::SocketState /*state*/) {} + +void SmtpClient::socketError(QAbstractSocket::SocketError /*socketError*/) {} + +void SmtpClient::socketReadyRead() {} + +/* [5] --- */ diff --git a/src/ui/AttachmentTableModel.cpp b/src/ui/AttachmentTableModel.cpp deleted file mode 100644 index 79cbdf9b..00000000 --- a/src/ui/AttachmentTableModel.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar 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 General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#include "ui/AttachmentTableModel.h" - -#include <utility> - -/** compare with http://doc.qt.nokia.com/4.6/itemviews-addressbook.html - */ - -AttachmentTableModel::AttachmentTableModel(QObject *parent) : - QAbstractTableModel(parent) { -} - -AttachmentTableModel::AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent) : - QAbstractTableModel(parent) { - listOfMimeparts = std::move(mimeparts); -} - - -void AttachmentTableModel::add(const MimePart &mp) { - listOfMimeparts.append(mp); - //QModelIndex changedIndex0 = createIndex(listOfMimeparts.size(), 0); - //QModelIndex changedIndex1 = createIndex(listOfMimeparts.size(), 1); - - //emit(dataChanged(changedIndex0, changedIndex1)); - // TODO: check the data-changed signal - // reset(); -} - -MimePart AttachmentTableModel::getSelectedMimePart(QModelIndex index) { - return listOfMimeparts.at(index.row()); -} - -MimePart AttachmentTableModel::getMimePart(int index) { - return listOfMimeparts.at(index); -} - -/*QList<MimePart> AttachmentTableModel::getSelectedMimeParts(QModelIndexList indexes){ - - foreach(QModelIndex index, indexes) { - qDebug() << "ir: "<< index.row(); - } - -}*/ - -int AttachmentTableModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return listOfMimeparts.size(); -} - -int AttachmentTableModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return 2; -} - -QVariant AttachmentTableModel::data(const QModelIndex &index, int role) const { - - //qDebug() << "called, index: " << index.column(); - - if (!index.isValid()) - return QVariant(); - - if (index.row() >= listOfMimeparts.size() || index.row() < 0) - return QVariant(); - - if (role == Qt::DisplayRole) { - MimePart mp = listOfMimeparts.at(index.row()); - - if (index.column() == 0) - return mp.header.getParam("Content-Type", "name"); - if (index.column() == 1) - return mp.header.getValue("Content-Type"); - - } - - // set icon - // TODO more generic matching, e.g. for audio - if (role == Qt::DecorationRole && index.column() == 0) { - MimePart mp = listOfMimeparts.at(index.row()); - QString icon; - if (mp.header.getValue("Content-Type").startsWith("image")) { - icon = ":mimetypes/image-x-generic.png"; - } else { - icon = mp.header.getValue("Content-Type").replace("/", "-"); - icon = ":mimetypes/" + icon + ".png"; - } - if (!QFile::exists(icon)) icon = ":mimetypes/unknown.png"; - return QIcon(icon); - } - - return QVariant(); -} - -QVariant AttachmentTableModel::headerData(int section, Qt::Orientation orientation, int role) const { - //qDebug() << "called, section: " << section; - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) { - switch (section) { - case 0: - return tr("Filename"); - - case 1: - return tr("Contenttype"); - - default: - return QVariant(); - } - } - return QVariant(); -} diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp index d95a9bfe..7065e41c 100644 --- a/src/ui/main_window/MainWindowSlotUI.cpp +++ b/src/ui/main_window/MainWindowSlotUI.cpp @@ -145,13 +145,6 @@ void MainWindow::slotOpenSettingsDialog() { importButton->setToolButtonStyle(buttonStyle); fileEncButton->setToolButtonStyle(buttonStyle); - // Mime-settings - if (settings.value("mime/parseMime").toBool()) { - createAttachmentDock(); - } else if (attachmentDockCreated) { - closeAttachmentDock(); - } - // restart mainwindow if necessary if (getRestartNeeded()) { if (edit->maybeSaveAnyTab()) { diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 0f7f1040..21f6e3b7 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -447,26 +447,4 @@ void MainWindow::createDockWindows() { infoBoardDock->setWidget(infoBoard); infoBoardDock->widget()->layout()->setContentsMargins(0, 0, 0, 0); viewMenu->addAction(infoBoardDock->toggleViewAction()); - - /* Attachments-Dockwindow - */ - if (settings.value("mime/parseMime").toBool()) { - createAttachmentDock(); - } -} - -void MainWindow::createAttachmentDock() { - if (attachmentDockCreated) { - return; - } - mAttachments = new Attachments(); - attachmentDock = new QDockWidget(tr("Attached files:"), this); - attachmentDock->setObjectName("AttachmentDock"); - attachmentDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); - addDockWidget(Qt::LeftDockWidgetArea, attachmentDock); - attachmentDock->setWidget(mAttachments); - // hide till attachment is decrypted - viewMenu->addAction(attachmentDock->toggleViewAction()); - attachmentDock->hide(); - attachmentDockCreated = true; } diff --git a/src/ui/widgets/Attachments.cpp b/src/ui/widgets/Attachments.cpp deleted file mode 100644 index 8f741f66..00000000 --- a/src/ui/widgets/Attachments.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar 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 General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -/* TODO: - * - check content encoding (base64 / quoted-printable) and apply appropriate opperation (maybe already in mime.cpp) - * - check memory usage, use less copy operations / more references - * - possibility to clear attachment-view , e.g. with decryption or encrypting a new message - * - save all: like in thunderbird, one folder, all files go there - */ - -/* - * - save, delete (clear) all - * - each line save & clear button - * - attached files to view-menu - * - also an open button, whichs should save file to tmp-folder, and open with correct app (via QDesktopServices) - */ - - -#include "ui/widgets/Attachments.h" - -Attachments::Attachments(QWidget *parent) - : QWidget(parent) { - table = new AttachmentTableModel(this); - - tableView = new QTableView; - tableView->setModel(table); - tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - // only one entry should be selected at time - tableView->setSelectionMode(QAbstractItemView::SingleSelection); - tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); - tableView->setFocusPolicy(Qt::NoFocus); - tableView->setAlternatingRowColors(true); - tableView->verticalHeader()->hide(); - tableView->setShowGrid(false); - tableView->setColumnWidth(0, 300); - tableView->horizontalHeader()->setStretchLastSection(true); - - auto *layout = new QVBoxLayout; - layout->addWidget(tableView); - layout->setContentsMargins(0, 0, 0, 0); - setLayout(layout); - createActions(); - -} - -void Attachments::contextMenuEvent(QContextMenuEvent *event) { - QMenu menu(this); - menu.addAction(saveFileAct); - // enable open with only if allowed by user - if (settings.value("mime/openAttachment").toBool()) - menu.addAction(openFileAct); - - menu.exec(event->globalPos()); -} - -void Attachments::createActions() { - saveFileAct = new QAction(tr("Save File"), this); - saveFileAct->setToolTip(tr("Save this file")); - saveFileAct->setIcon(QIcon(":filesave.png")); - connect(saveFileAct, SIGNAL(triggered()), this, SLOT(slotSaveFile())); - - openFileAct = new QAction(tr("Open File"), this); - openFileAct->setToolTip(tr("Open this file")); - openFileAct->setIcon(QIcon(":fileopen.png")); - connect(openFileAct, SIGNAL(triggered()), this, SLOT(slotOpenFile())); - -} - -void Attachments::slotSaveFile() { - - QModelIndexList indexes = tableView->selectionModel()->selection().indexes(); - - if (indexes.empty()) { - return; - } - - // only singe-selection possible now: TODO: foreach - MimePart mp = table->getMimePart(indexes.at(0).row()); - QString filename = mp.header.getParam("Content-Type", "name"); - // TODO: find out why filename is quoted - filename.chop(1); - filename.remove(0, 1); - // TODO: check if really base64 - saveByteArrayToFile(QByteArray::fromBase64(mp.body), filename); - -} - -void Attachments::saveByteArrayToFile(QByteArray outBuffer, QString filename) { - - //QString path=""; - QString path = std::move(filename); - QString outfileName = QFileDialog::getSaveFileName(this, tr("Save File"), path); - - if (outfileName.isEmpty()) return; - - QFile outfile(outfileName); - if (!outfile.open(QFile::WriteOnly)) { - QMessageBox::warning(this, tr("File"), - tr("Cannot write file %1:\n%2.") - .arg(outfileName) - .arg(outfile.errorString())); - return; - } - - QDataStream out(&outfile); - out.writeRawData(outBuffer.data(), outBuffer.length()); - outfile.close(); -} - -/** - * WIP: TODO: - * - create attachments dir if not existing - * - ask for cleanup of dir on exit - * - remove code-duplication with saveByteArrayToFile - */ -void Attachments::slotOpenFile() { - - // TODO: make attachmentdir constant or configurable - QString attachmentDir = qApp->applicationDirPath() + "/attachments/"; - //QDir p = QDir(qApp->applicationDirPath() + "/attachments/"); - if (!QDir(attachmentDir).exists()) { - QDir().mkpath(attachmentDir); - } - - QModelIndexList indexes = tableView->selectionModel()->selection().indexes(); - MimePart mp = table->getMimePart(indexes.at(0).row()); - -// qDebug() << "mime: " << mp.header.getValue("Content-Type"); - - QString filename = mp.header.getParam("Content-Type", "name"); - // TODO: find out why filename is quoted -// qDebug() << "file: " << filename; - filename.chop(1); - filename.remove(0, 1); - filename.prepend(attachmentDir); - - // qDebug() << "file: " << filename; - QByteArray outBuffer = QByteArray::fromBase64(mp.body); - - - QFile outfile(filename); - if (!outfile.open(QFile::WriteOnly)) { - QMessageBox::warning(this, tr("File"), - tr("Cannot write file %1:\n%2.") - .arg(filename) - .arg(outfile.errorString())); - return; - } - - QDataStream out(&outfile); - out.writeRawData(outBuffer.data(), outBuffer.length()); - outfile.close(); - QDesktopServices::openUrl(QUrl("file://" + filename, QUrl::TolerantMode)); -} - -void Attachments::addMimePart(MimePart *mp) { - table->add(*mp); -} - |