diff options
Diffstat (limited to 'src/m_email')
| -rw-r--r-- | src/m_email/EMailMetaDataDialog.cpp | 435 | ||||
| -rw-r--r-- | src/m_email/EMailMetaDataDialog.h | 40 | ||||
| -rw-r--r-- | src/m_email/EMailMetaDataDialog.ui | 430 | ||||
| -rw-r--r-- | src/m_email/EMailModule.cpp | 56 | 
4 files changed, 652 insertions, 309 deletions
diff --git a/src/m_email/EMailMetaDataDialog.cpp b/src/m_email/EMailMetaDataDialog.cpp index 11583b9..d3ef010 100644 --- a/src/m_email/EMailMetaDataDialog.cpp +++ b/src/m_email/EMailMetaDataDialog.cpp @@ -41,6 +41,9 @@  static const QRegularExpression kNameEmailStringRegex{      R"(^\s*(.*)\s*<\s*([^<>@\s]+@[^<>@\s]+)\s*>\s*$)"}; +static const QRegularExpression kNameEmailStringValidateRegex( +    R"(^\s*(.*\s*)?<\s*([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)\s*>\s*$|(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$))"); +  auto ParseEmailString(const QString& input, QString& name,                        QString& email) -> bool {    QRegularExpressionMatch match = kNameEmailStringRegex.match(input); @@ -69,14 +72,42 @@ class ContentTypeField : public vmime::contentTypeField {    ContentTypeField() = default;  }; -EMailMetaDataDialog::EMailMetaDataDialog(QByteArray body_data, QWidget* parent) +EMailMetaDataDialog::EMailMetaDataDialog(int mode, QWidget* parent)      : QDialog(parent),        ui_(QSharedPointer<Ui_EMailMetaDataDialog>::create()), -      body_data_(std::move(body_data)) { +      mode_(mode) {    ui_->setupUi(this); -  connect(ui_->exportMailButton, &QPushButton::clicked, this, -          &EMailMetaDataDialog::slot_export_eml_data); +  ui_->ccEdit->setHidden(true); +  ui_->ccLabel->setHidden(true); +  ui_->bccEdit->setHidden(true); +  ui_->bccLabel->setHidden(true); + +  if (mode == 0) { +    connect(ui_->okButton, &QPushButton::clicked, this, +            &EMailMetaDataDialog::slot_sign_eml_data); +  } else { +    connect(ui_->okButton, &QPushButton::clicked, this, +            &EMailMetaDataDialog::slot_encrypt_eml_data); +  } + +  connect(ui_->cancelButton, &QPushButton::clicked, this, &QDialog::close); + +  connect(ui_->ccButton, &QPushButton::clicked, this, [this]() { +    ui_->ccEdit->setHidden(!ui_->ccEdit->isHidden()); +    ui_->ccLabel->setHidden(!ui_->ccLabel->isHidden()); +  }); + +  connect(ui_->bccButton, &QPushButton::clicked, this, [this]() { +    ui_->bccEdit->setHidden(!ui_->bccEdit->isHidden()); +    ui_->bccLabel->setHidden(!ui_->bccLabel->isHidden()); +  }); + +  connect(this, &EMailMetaDataDialog::SignalEMLDataGenerateSuccess, this, +          &QDialog::close); + +  connect(this, &EMailMetaDataDialog::SignalEMLDataGenerateFailed, this, +          &QDialog::close);    setModal(true);    setAttribute(Qt::WA_DeleteOnClose); @@ -85,13 +116,20 @@ EMailMetaDataDialog::EMailMetaDataDialog(QByteArray body_data, QWidget* parent)  Q_VARIANT_Q_OBJECT_FACTORY_DEFINE(CreateEMailMetaDataDialog,                                    [](QVariant data) -> void* { -                                    return new EMailMetaDataDialog( -                                        data.toByteArray(), nullptr); +                                    return new EMailMetaDataDialog(data.toInt(), +                                                                   nullptr);                                    }); -void EMailMetaDataDialog::slot_export_eml_data() { +void EMailMetaDataDialog::slot_sign_eml_data() {    // sign key is a must -  if (sign_key_.isEmpty()) emit SignalEMLDataGenerateFailed("No Sign Key"); +  if (keys_.isEmpty()) emit SignalEMLDataGenerateFailed("No Sign Key"); + +  // only allow one sign key +  const auto sign_key = keys_.front(); + +  // validate +  slot_validate_inputs_and_show_errors(); +  if (!ui_->errorLabel->text().trimmed().isEmpty()) return;    auto from = ui_->fromEdit->text();    auto to = ui_->toEdit->text(); @@ -203,7 +241,7 @@ void EMailMetaDataDialog::slot_export_eml_data() {      auto public_key_part_header = public_key_part->getHeader(); -    auto public_key_name = QString("OpenPGP_0x%1.asc").arg(sign_key_.toUpper()); +    auto public_key_name = QString("OpenPGP_0x%1.asc").arg(sign_key.toUpper());      auto public_key_part_content_type_header_field =          public_key_part_header->getField<vmime::contentTypeField>(              vmime::fields::CONTENT_TYPE); @@ -250,7 +288,7 @@ void EMailMetaDataDialog::slot_export_eml_data() {      signature_part_content_disp_header_field->setFilename(          vmime::word({"OpenPGP_signature.asc"})); -    auto public_key = UDUP(GFGpgPublicKey(channel_, QDUP(sign_key_), 1)); +    auto public_key = UDUP(GFGpgPublicKey(channel_, QDUP(sign_key), 1));      if (public_key.isEmpty()) {        emit SignalEMLDataGenerateFailed("Get Public Key of Sign Key Failed");        return; @@ -287,24 +325,19 @@ void EMailMetaDataDialog::slot_export_eml_data() {      mime_part_part_body->setContents(mime_part_body_content);      auto container_raw_data = -        container_part->generate(vmime::lineLengthLimits::infinite); -    qDebug().noquote() << "\n" << container_raw_data; +        Q_SC(container_part->generate(vmime::lineLengthLimits::infinite)); -    container_raw_data = -        container_part->generate(vmime::lineLengthLimits::infinite); -    qDebug().noquote() << "\n" << container_raw_data; - -    auto container_raw_data_hash = -        QCryptographicHash::hash(container_raw_data, QCryptographicHash::Sha1); +    auto container_raw_data_hash = QCryptographicHash::hash( +        container_raw_data.toLatin1(), QCryptographicHash::Sha1);      FLOG_DEBUG("raw content of signature hash: %1",                 container_raw_data_hash.toHex());      FLOG_DEBUG("MIME Raw Data For Signature: %1", container_raw_data); -    FLOG_DEBUG("Signature Channel: %1, Sign Key: %2", channel_, sign_key_); +    FLOG_DEBUG("Signature Channel: %1, Sign Key: %2", channel_, sign_key);      GFGpgSignResult* s; -    auto ret = GFGpgSignData(channel_, QListToCharArray({sign_key_}), 1, -                             QDUP(Q_SC(container_raw_data)), 1, 1, &s); +    auto ret = GFGpgSignData(channel_, QListToCharArray({sign_key}), 1, +                             QDUP(container_raw_data), 1, 1, &s);      if (ret != 0) {        emit SignalEMLDataGenerateFailed("Sign Failed"); @@ -350,18 +383,26 @@ void EMailMetaDataDialog::slot_export_eml_data() {  void EMailMetaDataDialog::slot_export_encrypted_data() {} -void EMailMetaDataDialog::SetSignKey(QString k) { -  sign_key_ = std::move(k); -  slot_set_from_field_by_sign_key(); +void EMailMetaDataDialog::SetKeys(QStringList k) { +  keys_ = std::move(k); + +  if (mode_ == 0) { +    slot_set_from_field_by_sign_key(); +  } else { +    slot_set_to_field_by_encrypt_keys(); +  }  }  void EMailMetaDataDialog::SetChannel(int c) { channel_ = c; }  void EMailMetaDataDialog::slot_set_from_field_by_sign_key() { +  // only allow one sign key +  const auto sign_key = keys_.front(); +    GFGpgKeyUID* s; -  auto ret = GFGpgKeyPrimaryUID(channel_, QDUP(sign_key_), &s); +  auto ret = GFGpgKeyPrimaryUID(channel_, QDUP(sign_key), &s);    if (ret != 0) { -    FLOG_WARN("cannot get primary uid from sign key %1, ret: %2", sign_key_, +    FLOG_WARN("cannot get primary uid from sign key %1, ret: %2", sign_key,                ret);      return;    } @@ -374,3 +415,345 @@ void EMailMetaDataDialog::slot_set_from_field_by_sign_key() {    ui_->fromEdit->setText(QString("%1 <%2>").arg(from_name_).arg(from_email_));  } + +void EMailMetaDataDialog::slot_validate_inputs_and_show_errors() { +  QString error_message; + +  if (ui_->fromEdit->text().trimmed().isEmpty()) { +    error_message = tr("The 'From' field cannot be empty."); +  } else if (!is_valid_email(ui_->fromEdit->text().trimmed())) { +    error_message = tr("The 'From' field must contain a valid email address."); +  } + +  if (error_message.isEmpty() && ui_->toEdit->text().trimmed().isEmpty()) { +    error_message = tr("The 'To' field cannot be empty."); +  } else if (error_message.isEmpty() && +             !are_valid_emails(ui_->toEdit->text())) { +    error_message = +        tr("One or more 'To' addresses are invalid. Please separate multiple " +           "addresses with \";\"."); +  } + +  if (error_message.isEmpty() && !ui_->ccEdit->text().trimmed().isEmpty()) { +    if (!are_valid_emails(ui_->ccEdit->text())) { +      error_message = +          tr("One or more 'CC' addresses are invalid. Please separate " +             "multiple addresses with \";\"."); +    } +  } + +  if (error_message.isEmpty() && !ui_->bccEdit->text().trimmed().isEmpty()) { +    if (!are_valid_emails(ui_->bccEdit->text())) { +      error_message = +          tr("One or more 'BCC' addresses are invalid. Please separate " +             "multiple addresses with \";\"."); +    } +  } + +  if (error_message.isEmpty() && ui_->subjectEdit->text().trimmed().isEmpty()) { +    error_message = tr("The 'Subject' field cannot be empty."); +  } + +  if (!error_message.isEmpty()) { +    ui_->errorLabel->setText(error_message); +    ui_->errorLabel->setStyleSheet("QLabel { color : red; }"); +  } else { +    ui_->errorLabel->clear(); +  } +} + +auto EMailMetaDataDialog::are_valid_emails(const QString& emails) -> bool { +  QStringList email_list = emails.split(';', Qt::SkipEmptyParts); +  for (const QString& email : email_list) { +    if (!is_valid_email(email.trimmed())) { +      return false; +    } +  } +  return true; +} + +auto EMailMetaDataDialog::is_valid_email(const QString& email) -> bool { +  return kNameEmailStringValidateRegex.match(email).hasMatch(); +} + +void EMailMetaDataDialog::SetBodyData(QByteArray b) { +  body_data_ = std::move(b); +} + +void EMailMetaDataDialog::slot_encrypt_eml_data() { +  if (keys_.isEmpty()) { +    emit SignalEMLDataGenerateFailed("No Encryption Key Selected"); +    return; +  } + +  const auto encrypt_key = keys_.front(); + +  slot_validate_inputs_and_show_errors(); +  if (!ui_->errorLabel->text().trimmed().isEmpty()) { +    return; +  } + +  auto from = ui_->fromEdit->text(); +  auto to = ui_->toEdit->text(); +  auto cc = ui_->ccEdit->text(); +  auto bcc = ui_->bccEdit->text(); +  auto subject = ui_->subjectEdit->text(); + +  auto recipient_list = to.split(';', Qt::SkipEmptyParts); +  auto cc_list = cc.split(';', Qt::SkipEmptyParts); +  auto bcc_list = bcc.split(';', Qt::SkipEmptyParts); + +  QString name; +  QString email; + +  try { +    vmime::messageBuilder plaintext_msg_builder; + +    if (ParseEmailString(from, name, email)) { +      plaintext_msg_builder.setExpeditor( +          vmime::mailbox(vmime::text(name.toStdString()), email.toStdString())); +    } else { +      plaintext_msg_builder.setExpeditor(vmime::mailbox(from.toStdString())); +    } + +    for (const QString& recipient : recipient_list) { +      auto trimmed_recipient = recipient.trimmed(); +      if (ParseEmailString(trimmed_recipient, name, email)) { +        plaintext_msg_builder.getRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>(vmime::text(name.toStdString()), +                                               email.toStdString())); +      } else { +        plaintext_msg_builder.getRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>( +                trimmed_recipient.toStdString())); +      } +    } + +    for (const QString& recipient : cc_list) { +      auto trimmed_recipient = recipient.trimmed(); +      if (ParseEmailString(trimmed_recipient, name, email)) { +        plaintext_msg_builder.getCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>(vmime::text(name.toStdString()), +                                               email.toStdString())); +      } else { +        plaintext_msg_builder.getCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>( +                trimmed_recipient.toStdString())); +      } +    } + +    for (const QString& recipient : bcc_list) { +      auto trimmed_recipient = recipient.trimmed(); +      if (ParseEmailString(trimmed_recipient, name, email)) { +        plaintext_msg_builder.getBlindCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>(vmime::text(name.toStdString()), +                                               email.toStdString())); +      } else { +        plaintext_msg_builder.getBlindCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>( +                trimmed_recipient.toStdString())); +      } +    } + +    plaintext_msg_builder.setSubject(vmime::text(subject.toStdString())); + +    vmime::shared_ptr<vmime::message> plaintext_msg = +        plaintext_msg_builder.construct(); + +    auto plaintext_msg_header = plaintext_msg->getHeader(); + +    auto plaintext_msg_content_type_header_field = +        plaintext_msg_header->getField<vmime::contentTypeField>( +            vmime::fields::CONTENT_TYPE); +    plaintext_msg_content_type_header_field->setValue("text/plain"); +    plaintext_msg_content_type_header_field->appendParameter( +        vmime::make_shared<vmime::parameter>("charset", "UTF-8")); +    plaintext_msg_content_type_header_field->appendParameter( +        vmime::make_shared<vmime::parameter>("format", "flowed")); + +    auto plaintext_msg_content_trans_encode_field = +        plaintext_msg_header->getField( +            vmime::fields::CONTENT_TRANSFER_ENCODING); +    plaintext_msg_content_trans_encode_field->setValue("base64"); + +    auto plaintext_msg_body = plaintext_msg->getBody(); + +    auto mime_part_body_content = +        vmime::make_shared<vmime::stringContentHandler>(); +    mime_part_body_content->setData( +        body_data_.toBase64().toStdString(), +        vmime::encoding(vmime::encodingTypes::BASE64)); +    plaintext_msg_body->setContents(mime_part_body_content); + +    auto plaintext_eml_data = +        Q_SC(plaintext_msg->generate(vmime::lineLengthLimits::infinite)); + +    GFGpgEncryptionResult* enc_result = nullptr; +    auto ret = GFGpgEncryptData(channel_, QListToCharArray(keys_), keys_.size(), +                                QDUP(plaintext_eml_data), 1, &enc_result); + +    if (ret != 0) { +      emit SignalEMLDataGenerateFailed("Encryption Failed"); +      return; +    } + +    auto encrypted_data = UDUP(enc_result->encrypted_data); +    GFFreeMemory(enc_result); + +    vmime::messageBuilder msg_builder; + +    if (ParseEmailString(from, name, email)) { +      msg_builder.setExpeditor(vmime::mailbox(email.toStdString())); +    } else { +      msg_builder.setExpeditor(vmime::mailbox(from.toStdString())); +    } + +    for (const QString& recipient : recipient_list) { +      auto trimmed_recipient = recipient.trimmed(); +      if (ParseEmailString(trimmed_recipient, name, email)) { +        msg_builder.getRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>(email.toStdString())); +      } else { +        msg_builder.getRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>( +                trimmed_recipient.toStdString())); +      } +    } + +    for (const QString& recipient : cc_list) { +      auto trimmed_recipient = recipient.trimmed(); +      if (ParseEmailString(trimmed_recipient, name, email)) { +        msg_builder.getCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>(email.toStdString())); +      } else { +        msg_builder.getCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>( +                trimmed_recipient.toStdString())); +      } +    } + +    for (const QString& recipient : bcc_list) { +      auto trimmed_recipient = recipient.trimmed(); +      if (ParseEmailString(trimmed_recipient, name, email)) { +        msg_builder.getBlindCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>(email.toStdString())); +      } else { +        msg_builder.getBlindCopyRecipients().appendAddress( +            vmime::make_shared<vmime::mailbox>( +                trimmed_recipient.toStdString())); +      } +    } + +    msg_builder.setSubject(vmime::text("...")); + +    vmime::shared_ptr<vmime::message> msg = msg_builder.construct(); + +    auto header = msg->getHeader(); + +    // no Content-Transfer-Encoding +    header->removeField( +        header->getField(vmime::fields::CONTENT_TRANSFER_ENCODING)); + +    auto content_type_header_field = +        header->getField<vmime::contentTypeField>(vmime::fields::CONTENT_TYPE); +    content_type_header_field->setValue("multipart/encrypted"); +    content_type_header_field->appendParameter( +        vmime::make_shared<vmime::parameter>("protocol", +                                             "application/pgp-encrypted")); + +    auto root_part_boundary = vmime::body::generateRandomBoundaryString(); +    content_type_header_field->setBoundary(root_part_boundary); + +    auto root_body_part = vmime::make_shared<vmime::body>(); +    auto control_info_part = vmime::make_shared<vmime::bodyPart>(); +    auto encrypted_data_part = vmime::make_shared<vmime::bodyPart>(); + +    root_body_part->appendPart(control_info_part); +    root_body_part->appendPart(encrypted_data_part); +    msg->setBody(root_body_part); + +    root_body_part->setPrologText( +        "This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)"); + +    auto control_info_part_header = control_info_part->getHeader(); +    auto control_info_content_type_field = +        control_info_part_header->getField<vmime::contentTypeField>( +            vmime::fields::CONTENT_TYPE); +    control_info_content_type_field->setValue("application/pgp-encrypted"); + +    auto control_info_part_content_desc_header_field = +        control_info_part_header->getField(vmime::fields::CONTENT_DESCRIPTION); +    control_info_part_content_desc_header_field->setValue( +        "PGP/MIME version identification"); + +    auto control_info_body = control_info_part->getBody(); +    auto control_info_content = +        vmime::make_shared<vmime::stringContentHandler>("Version: 1"); +    control_info_body->setContents(control_info_content); + +    auto encrypted_data_part_header = encrypted_data_part->getHeader(); +    auto encrypted_data_content_type_field = +        encrypted_data_part_header->getField<vmime::contentTypeField>( +            vmime::fields::CONTENT_TYPE); +    encrypted_data_content_type_field->setValue("application/octet-stream"); +    encrypted_data_content_type_field->appendParameter( +        vmime::make_shared<vmime::parameter>("name", "encrypted.asc")); + +    auto encrypted_data_content_desc_header_field = +        encrypted_data_part_header->getField( +            vmime::fields::CONTENT_DESCRIPTION); +    encrypted_data_content_desc_header_field->setValue( +        "OpenPGP encrypted message"); + +    auto encrypted_data_content_disp_header_field = +        encrypted_data_part_header->getField<vmime::contentDispositionField>( +            vmime::fields::CONTENT_DISPOSITION); +    encrypted_data_content_disp_header_field->setValue("inline"); +    encrypted_data_content_disp_header_field->setFilename( +        vmime::word({"encrypted.asc"})); + +    auto encrypted_data_body = encrypted_data_part->getBody(); +    auto encrypted_data_content = +        vmime::make_shared<vmime::stringContentHandler>( +            encrypted_data.toStdString()); +    encrypted_data_body->setContents(encrypted_data_content); + +    auto eml_data = Q_SC(msg->generate(vmime::lineLengthLimits::infinite)); +    FLOG_DEBUG("EML Data: %1", eml_data); + +    emit SignalEMLDataGenerateSuccess(eml_data); + +    return; + +  } catch (const vmime::exception& e) { +    QMessageBox::critical(this, tr("Error"), +                          tr("Failed to export EML Data: %1").arg(e.what())); +    emit SignalEMLDataGenerateFailed(e.what()); +    return; +  } + +  emit SignalEMLDataGenerateFailed("Unknown Error"); +} + +void EMailMetaDataDialog::slot_set_to_field_by_encrypt_keys() { +  QStringList to_list; + +  for (const auto& key : keys_) { +    GFGpgKeyUID* s; +    auto ret = GFGpgKeyPrimaryUID(channel_, QDUP(key), &s); +    if (ret != 0) { +      FLOG_WARN("cannot get primary uid from sign key %1, ret: %2", key, ret); +      continue; +    } + +    from_name_ = UDUP(s->name); +    from_email_ = UDUP(s->email); +    auto comment = UDUP(s->comment); + +    GFFreeMemory(s); + +    to_list.append(QString("%1 <%2>").arg(from_name_).arg(from_email_)); +  } + +  ui_->toEdit->setText(to_list.join("; ")); +}
\ No newline at end of file diff --git a/src/m_email/EMailMetaDataDialog.h b/src/m_email/EMailMetaDataDialog.h index 983dc0a..c4ce5e4 100644 --- a/src/m_email/EMailMetaDataDialog.h +++ b/src/m_email/EMailMetaDataDialog.h @@ -39,7 +39,7 @@ class Ui_EMailMetaDataDialog;  class EMailMetaDataDialog : public QDialog {    Q_OBJECT   public: -  explicit EMailMetaDataDialog(QByteArray body_data, QWidget *parent); +  explicit EMailMetaDataDialog(int mode, QWidget* parent);    /**     * @brief Set the Channel object @@ -51,7 +51,14 @@ class EMailMetaDataDialog : public QDialog {     * @brief Set the Sign Keys object     *     */ -  void SetSignKey(QString k); +  void SetKeys(QStringList ks); + +  /** +   * @brief Set the Body Data object +   * +   * @param b +   */ +  void SetBodyData(QByteArray b);   signals: @@ -61,17 +68,42 @@ class EMailMetaDataDialog : public QDialog {   private slots: -  void slot_export_eml_data(); +  void slot_sign_eml_data(); + +  void slot_encrypt_eml_data();    void slot_export_encrypted_data();    void slot_set_from_field_by_sign_key(); +  void slot_set_to_field_by_encrypt_keys(); + +  void slot_validate_inputs_and_show_errors(); +   private: +  /** +   * @brief +   * +   * @param email +   * @return true +   * @return false +   */ +  static auto is_valid_email(const QString& email) -> bool; + +  /** +   * @brief +   * +   * @param emails +   * @return true +   * @return false +   */ +  static auto are_valid_emails(const QString& emails) -> bool; +    QSharedPointer<Ui_EMailMetaDataDialog> ui_; +  int mode_;    QByteArray body_data_;    int channel_; -  QString sign_key_; +  QStringList keys_;    QString from_name_;    QString from_email_;  }; diff --git a/src/m_email/EMailMetaDataDialog.ui b/src/m_email/EMailMetaDataDialog.ui index 977a535..ea503f8 100644 --- a/src/m_email/EMailMetaDataDialog.ui +++ b/src/m_email/EMailMetaDataDialog.ui @@ -6,8 +6,8 @@     <rect>      <x>0</x>      <y>0</y> -    <width>599</width> -    <height>522</height> +    <width>525</width> +    <height>346</height>     </rect>    </property>    <property name="cursor"> @@ -26,255 +26,111 @@     <bool>false</bool>    </property>    <layout class="QGridLayout" name="gridLayout"> -   <item row="0" column="0"> +   <property name="leftMargin"> +    <number>5</number> +   </property> +   <property name="topMargin"> +    <number>5</number> +   </property> +   <property name="rightMargin"> +    <number>5</number> +   </property> +   <property name="bottomMargin"> +    <number>5</number> +   </property> +   <item row="1" column="0">      <layout class="QVBoxLayout" name="verticalLayout">       <item> -      <widget class="QWidget" name="horizontalWidget" native="true"> -       <layout class="QHBoxLayout" name="horizontalLayout"> -        <property name="spacing"> -         <number>6</number> -        </property> -        <property name="leftMargin"> -         <number>0</number> -        </property> -        <property name="topMargin"> -         <number>0</number> -        </property> -        <property name="rightMargin"> -         <number>0</number> -        </property> -        <property name="bottomMargin"> -         <number>0</number> -        </property> -        <item> -         <widget class="QLabel" name="senderLabel"> -          <property name="text"> -           <string>From</string> -          </property> -          <property name="margin"> -           <number>5</number> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QLineEdit" name="fromEdit"/> -        </item> -        <item> -         <widget class="Line" name="line"> -          <property name="toolTipDuration"> -           <number>0</number> -          </property> -          <property name="autoFillBackground"> -           <bool>false</bool> -          </property> -          <property name="lineWidth"> -           <number>2</number> -          </property> -          <property name="orientation"> -           <enum>Qt::Orientation::Vertical</enum> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QPushButton" name="ccButton"> -          <property name="text"> -           <string>CC</string> -          </property> -          <property name="checkable"> -           <bool>true</bool> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QPushButton" name="bccButton"> -          <property name="text"> -           <string>BCC</string> -          </property> -          <property name="checkable"> -           <bool>true</bool> -          </property> -         </widget> -        </item> -       </layout> -      </widget> -     </item> -     <item> -      <widget class="QWidget" name="horizontalWidget_4" native="true"> -       <layout class="QHBoxLayout" name="horizontalLayout_4"> -        <property name="spacing"> -         <number>6</number> -        </property> -        <property name="leftMargin"> -         <number>0</number> -        </property> -        <property name="topMargin"> -         <number>0</number> -        </property> -        <property name="rightMargin"> -         <number>0</number> -        </property> -        <property name="bottomMargin"> -         <number>0</number> -        </property> -        <item> -         <widget class="QLabel" name="recipientLabel"> -          <property name="text"> -           <string>To</string> -          </property> -          <property name="margin"> -           <number>5</number> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QLineEdit" name="toEdit"/> -        </item> -        <item> -         <widget class="QPushButton" name="recipientsEditButton"> -          <property name="text"> -           <string>Edit Recipients(s)</string> -          </property> -         </widget> -        </item> -       </layout> -      </widget> -     </item> -     <item> -      <widget class="Line" name="line_2"> -       <property name="orientation"> -        <enum>Qt::Orientation::Horizontal</enum> -       </property> -      </widget> -     </item> -     <item> -      <widget class="QWidget" name="horizontalWidget_5" native="true"> -       <layout class="QHBoxLayout" name="horizontalLayout_6"> -        <property name="spacing"> -         <number>0</number> -        </property> -        <property name="leftMargin"> -         <number>0</number> -        </property> -        <property name="topMargin"> -         <number>0</number> -        </property> -        <property name="rightMargin"> -         <number>0</number> -        </property> -        <property name="bottomMargin"> -         <number>0</number> -        </property> -        <item> -         <widget class="QLabel" name="subjectLabel"> -          <property name="text"> -           <string>Subject</string> -          </property> -          <property name="margin"> -           <number>5</number> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QLineEdit" name="subjectEdit"/> -        </item> -       </layout> -      </widget> -     </item> -     <item> -      <widget class="Line" name="line_4"> -       <property name="orientation"> -        <enum>Qt::Orientation::Horizontal</enum> -       </property> -      </widget> +      <layout class="QHBoxLayout" name="horizontalLayout_8"> +       <item> +        <widget class="QLabel" name="senderLabel"> +         <property name="minimumSize"> +          <size> +           <width>50</width> +           <height>0</height> +          </size> +         </property> +         <property name="text"> +          <string>From</string> +         </property> +         <property name="margin"> +          <number>5</number> +         </property> +        </widget> +       </item> +       <item> +        <widget class="QLineEdit" name="fromEdit"/> +       </item> +      </layout>       </item>       <item> -      <widget class="QWidget" name="ccInputWidget" native="true"> -       <layout class="QHBoxLayout" name="horizontalLayout_2"> -        <property name="spacing"> -         <number>6</number> -        </property> -        <property name="leftMargin"> -         <number>0</number> -        </property> -        <property name="topMargin"> -         <number>0</number> -        </property> -        <property name="rightMargin"> -         <number>0</number> -        </property> -        <property name="bottomMargin"> -         <number>0</number> -        </property> -        <item> -         <widget class="QLabel" name="ccLabel"> -          <property name="text"> -           <string>CC</string> -          </property> -          <property name="margin"> -           <number>5</number> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QLineEdit" name="ccEdit"/> -        </item> -        <item> -         <widget class="QPushButton" name="ccEditButton"> -          <property name="text"> -           <string>Edit CC(s)</string> -          </property> -         </widget> -        </item> -       </layout> -      </widget> +      <layout class="QHBoxLayout" name="horizontalLayout_2"> +       <item> +        <widget class="QLabel" name="recipientLabel"> +         <property name="minimumSize"> +          <size> +           <width>50</width> +           <height>0</height> +          </size> +         </property> +         <property name="text"> +          <string>To</string> +         </property> +         <property name="margin"> +          <number>5</number> +         </property> +        </widget> +       </item> +       <item> +        <widget class="QLineEdit" name="toEdit"/> +       </item> +      </layout>       </item>       <item> -      <widget class="QWidget" name="bccInputWidget" native="true"> -       <layout class="QHBoxLayout" name="horizontalLayout_3"> -        <property name="spacing"> -         <number>6</number> -        </property> -        <property name="leftMargin"> -         <number>0</number> -        </property> -        <property name="topMargin"> -         <number>0</number> -        </property> -        <property name="rightMargin"> -         <number>0</number> -        </property> -        <property name="bottomMargin"> -         <number>0</number> -        </property> -        <item> -         <widget class="QLabel" name="bccLabel"> -          <property name="text"> -           <string>BCC</string> -          </property> -          <property name="margin"> -           <number>5</number> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QLineEdit" name="bccEdit"/> -        </item> -        <item> -         <widget class="QPushButton" name="bccEditButton"> -          <property name="text"> -           <string>Edit BCC(s)</string> -          </property> -         </widget> -        </item> -       </layout> -      </widget> +      <layout class="QHBoxLayout" name="horizontalLayout_3"> +       <item> +        <widget class="QLabel" name="ccLabel"> +         <property name="minimumSize"> +          <size> +           <width>50</width> +           <height>0</height> +          </size> +         </property> +         <property name="text"> +          <string>CC</string> +         </property> +         <property name="margin"> +          <number>5</number> +         </property> +        </widget> +       </item> +       <item> +        <widget class="QLineEdit" name="ccEdit"/> +       </item> +      </layout>       </item>       <item> -      <widget class="QLabel" name="tipsLabel"> -       <property name="text"> -        <string>Tips: You can fill in multiple email addresses, please separate them with ";".</string> -       </property> -      </widget> +      <layout class="QHBoxLayout" name="horizontalLayout_5"> +       <item> +        <widget class="QLabel" name="bccLabel"> +         <property name="minimumSize"> +          <size> +           <width>50</width> +           <height>0</height> +          </size> +         </property> +         <property name="text"> +          <string>BCC</string> +         </property> +         <property name="margin"> +          <number>5</number> +         </property> +        </widget> +       </item> +       <item> +        <widget class="QLineEdit" name="bccEdit"/> +       </item> +      </layout>       </item>       <item>        <widget class="Line" name="line_3"> @@ -284,61 +140,78 @@        </widget>       </item>       <item> -      <layout class="QHBoxLayout" name="horizontalLayout_5"/> -     </item> -     <item> -      <layout class="QHBoxLayout" name="horizontalLayout_10"> -       <item alignment="Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter"> -        <widget class="QLabel" name="keysLabel"> +      <layout class="QHBoxLayout" name="horizontalLayout"> +       <item> +        <widget class="QLabel" name="subjectLabel"> +         <property name="minimumSize"> +          <size> +           <width>50</width> +           <height>0</height> +          </size> +         </property>           <property name="text"> -          <string>GPG Keys:</string> +          <string>Subject</string> +         </property> +         <property name="margin"> +          <number>5</number>           </property>          </widget>         </item>         <item> -        <widget class="QLabel" name="recipientsKeyValueLabel"> -         <property name="sizePolicy"> -          <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> -           <horstretch>0</horstretch> -           <verstretch>0</verstretch> -          </sizepolicy> -         </property> -         <property name="text"> -          <string/> -         </property> -         <property name="wordWrap"> -          <bool>true</bool> +        <widget class="QLineEdit" name="subjectEdit"> +         <property name="minimumSize"> +          <size> +           <width>0</width> +           <height>0</height> +          </size>           </property>          </widget>         </item>        </layout>       </item>       <item> -      <widget class="QListWidget" name="keyListWidget"/> -     </item> -     <item> -      <widget class="QLabel" name="errorLabel"> +      <widget class="QLabel" name="tipsLabel">         <property name="text"> -        <string/> +        <string>Tips: You can fill in multiple email addresses, please separate them with ";", except for the 'From' field.</string> +       </property> +       <property name="wordWrap"> +        <bool>true</bool>         </property>        </widget>       </item>       <item> -      <widget class="Line" name="line_5"> +      <spacer name="verticalSpacer">         <property name="orientation"> -        <enum>Qt::Orientation::Horizontal</enum> +        <enum>Qt::Orientation::Vertical</enum> +       </property> +       <property name="sizeHint" stdset="0"> +        <size> +         <width>20</width> +         <height>40</height> +        </size> +       </property> +      </spacer> +     </item> +     <item> +      <widget class="QLabel" name="errorLabel"> +       <property name="text"> +        <string/>         </property>        </widget>       </item>       <item>        <layout class="QHBoxLayout" name="horizontalLayout_7">         <item> -        <widget class="QCheckBox" name="encryptCheckBox"> +        <widget class="QPushButton" name="ccButton">           <property name="text"> -          <string>Encrypt</string> +          <string>CC</string>           </property> -         <property name="checked"> -          <bool>true</bool> +        </widget> +       </item> +       <item> +        <widget class="QPushButton" name="bccButton"> +         <property name="text"> +          <string>BCC</string>           </property>          </widget>         </item> @@ -355,10 +228,17 @@           </property>          </spacer>         </item> +       <item> +        <widget class="QPushButton" name="cancelButton"> +         <property name="text"> +          <string>Cancel</string> +         </property> +        </widget> +       </item>         <item alignment="Qt::AlignmentFlag::AlignRight"> -        <widget class="QPushButton" name="exportMailButton"> +        <widget class="QPushButton" name="okButton">           <property name="text"> -          <string>Export</string> +          <string>OK</string>           </property>          </widget>         </item> diff --git a/src/m_email/EMailModule.cpp b/src/m_email/EMailModule.cpp index 1262c75..ee46bb9 100644 --- a/src/m_email/EMailModule.cpp +++ b/src/m_email/EMailModule.cpp @@ -65,7 +65,8 @@ auto GFRegisterModule() -> int {    LISTEN("EMAIL_VERIFY_EML_DATA");    LISTEN("EMAIL_DECRYPT_EML_DATA"); -  LISTEN("EMAIL_EXPORT_EML_DATA"); +  LISTEN("EMAIL_SIGN_EML_DATA"); +  LISTEN("EMAIL_ENCRYPT_EML_DATA");    return 0;  } @@ -405,7 +406,7 @@ REGISTER_EVENT_HANDLER(EMAIL_DECRYPT_EML_DATA, [](const MEvent& event) -> int {    return 0;  }); -REGISTER_EVENT_HANDLER(EMAIL_EXPORT_EML_DATA, [](const MEvent& event) -> int { +REGISTER_EVENT_HANDLER(EMAIL_SIGN_EML_DATA, [](const MEvent& event) -> int {    if (event["body_data"].isEmpty()) CB_ERR(event, -1, "body_data is empty");    if (event["channel"].isEmpty()) CB_ERR(event, -1, "channel is empty");    if (event["sign_key"].isEmpty()) CB_ERR(event, -1, "sign_key is empty"); @@ -417,13 +418,59 @@ REGISTER_EVENT_HANDLER(EMAIL_EXPORT_EML_DATA, [](const MEvent& event) -> int {    auto data = QByteArray::fromBase64(QString(event["body_data"]).toLatin1()); -  auto* dialog = GUI_OBJECT(CreateEMailMetaDataDialog, {data}); +  auto* dialog = GUI_OBJECT(CreateEMailMetaDataDialog, 0);    auto* r_dialog =        qobject_cast<EMailMetaDataDialog*>(static_cast<QObject*>(dialog));    if (r_dialog == nullptr)      CB_ERR(event, -1, "convert dialog to r_dialog failed"); + +  r_dialog->SetChannel(channel); +  r_dialog->SetKeys({sign_key}); +  r_dialog->SetBodyData({data}); + +  GFUIShowDialog(dialog, nullptr); + +  QObject::connect(r_dialog, &EMailMetaDataDialog::SignalEMLDataGenerateSuccess, +                   r_dialog, [=](QString eml_data) { +                     // callback +                     CB(event, GFGetModuleID(), +                        { +                            {"ret", QString::number(0)}, +                            {"eml_data", eml_data}, +                        }); +                   }); + +  QObject::connect(r_dialog, &EMailMetaDataDialog::SignalEMLDataGenerateFailed, +                   r_dialog, [=](QString error) { +                     // callback +                     CB_ERR(event, -1, "Generate EML Data Failed: " + error); +                   }); + +  return 0; +}); + +REGISTER_EVENT_HANDLER(EMAIL_ENCRYPT_EML_DATA, [](const MEvent& event) -> int { +  if (event["body_data"].isEmpty()) CB_ERR(event, -1, "body_data is empty"); +  if (event["channel"].isEmpty()) CB_ERR(event, -1, "channel is empty"); +  if (event["encrypt_keys"].isEmpty()) +    CB_ERR(event, -1, "encrypt_keys is empty"); + +  auto channel = event.value("channel", "0").toInt(); +  auto encrypt_keys = event.value("encrypt_keys", "").split(';'); + +  FLOG_DEBUG("eml encrypt keys: %1", encrypt_keys.join(';')); + +  auto data = QByteArray::fromBase64(QString(event["body_data"]).toLatin1()); + +  auto* dialog = GUI_OBJECT(CreateEMailMetaDataDialog, 1); +  auto* r_dialog = +      qobject_cast<EMailMetaDataDialog*>(static_cast<QObject*>(dialog)); +  if (r_dialog == nullptr) +    CB_ERR(event, -1, "convert dialog to r_dialog failed"); +    r_dialog->SetChannel(channel); -  r_dialog->SetSignKey(sign_key); +  r_dialog->SetKeys(encrypt_keys); +  r_dialog->SetBodyData({data});    GFUIShowDialog(dialog, nullptr); @@ -445,6 +492,7 @@ REGISTER_EVENT_HANDLER(EMAIL_EXPORT_EML_DATA, [](const MEvent& event) -> int {    return 0;  }); +  auto GFDeactivateModule() -> int { return 0; }  auto GFUnregisterModule() -> int {  | 
