Composer: don't pass along the sender specification
[trojita.git] / src / Gui / ComposeWidget.cpp
blobae579a704d21b919f735d9b8462706868c4abf6e
1 /* Copyright (C) 2006 - 2012 Jan Kundrát <jkt@flaska.net>
3 This file is part of the Trojita Qt IMAP e-mail client,
4 http://trojita.flaska.net/
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <QBuffer>
23 #include <QFileDialog>
24 #include <QKeyEvent>
25 #include <QMenu>
26 #include <QMessageBox>
27 #include <QProgressDialog>
28 #include <QPushButton>
29 #include <QSettings>
31 #include "AbstractAddressbook.h"
32 #include "AutoCompletion.h"
33 #include "ComposeWidget.h"
34 #include "FromAddressProxyModel.h"
35 #include "Window.h"
36 #include "ui_ComposeWidget.h"
38 #include "Composer/SenderIdentitiesModel.h"
39 #include "Common/SettingsNames.h"
40 #include "MSA/Sendmail.h"
41 #include "MSA/SMTP.h"
42 #include "Imap/Model/Model.h"
43 #include "Imap/Tasks/AppendTask.h"
44 #include "Imap/Tasks/GenUrlAuthTask.h"
45 #include "Imap/Tasks/UidSubmitTask.h"
47 namespace
49 enum { OFFSET_OF_FIRST_ADDRESSEE = 1 };
52 namespace Gui
55 ComposeWidget::ComposeWidget(MainWindow *parent) :
56 QWidget(parent, Qt::Window),
57 ui(new Ui::ComposeWidget),
58 m_appendUidReceived(false), m_appendUidValidity(0), m_appendUid(0), m_genUrlAuthReceived(false),
59 m_mainWindow(parent)
61 Q_ASSERT(m_mainWindow);
62 m_composer = new Imap::Mailbox::MessageComposer(m_mainWindow->imapModel(), this);
63 m_composer->setPreloadEnabled(shouldBuildMessageLocally());
65 ui->setupUi(this);
66 sendButton = ui->buttonBox->addButton(tr("Send"), QDialogButtonBox::AcceptRole);
67 connect(sendButton, SIGNAL(clicked()), this, SLOT(send()));
68 cancelButton = ui->buttonBox->addButton(QDialogButtonBox::Cancel);
69 connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
70 ui->attachmentsView->setModel(m_composer);
71 connect(ui->attachButton, SIGNAL(clicked()), this, SLOT(slotAskForFileAttachment()));
72 ui->attachmentsView->setContextMenuPolicy(Qt::ActionsContextMenu);
74 m_actionRemoveAttachment = new QAction(tr("Remove"), this);
75 connect(m_actionRemoveAttachment, SIGNAL(triggered()), this, SLOT(slotRemoveAttachment()));
76 ui->attachmentsView->addAction(m_actionRemoveAttachment);
78 connect(ui->attachmentsView, SIGNAL(itemDroppedOut()), SLOT(slotRemoveAttachment()));
80 m_completionPopup = new QMenu(this);
81 m_completionPopup->installEventFilter(this);
82 connect (m_completionPopup, SIGNAL(triggered(QAction*)), SLOT(completeRecipient(QAction*)));
84 // TODO: make this configurable?
85 m_completionCount = 8;
87 m_recipientListUpdateTimer = new QTimer(this);
88 m_recipientListUpdateTimer->setSingleShot(true);
89 m_recipientListUpdateTimer->setInterval(250);
90 connect(m_recipientListUpdateTimer, SIGNAL(timeout()), SLOT(updateRecipientList()));
92 // Ask for a fixed-width font. The problem is that these names wary acros platforms,
93 // but the following works well -- at first, we come up with a made-up name, and then
94 // let the Qt font substitution algorithm do its magic.
95 QFont font(QLatin1String("x-trojita-terminus-like-fixed-width"));
96 font.setStyleHint(QFont::TypeWriter);
97 ui->mailText->setFont(font);
99 connect(ui->mailText, SIGNAL(urlsAdded(QList<QUrl>)), SLOT(slotAttachFiles(QList<QUrl>)));
100 connect(ui->mailText, SIGNAL(sendRequest()), SLOT(send()));
102 FromAddressProxyModel *proxy = new FromAddressProxyModel(this);
103 proxy->setSourceModel(m_mainWindow->senderIdentitiesModel());
104 ui->sender->setModel(proxy);
107 ComposeWidget::~ComposeWidget()
109 delete ui;
112 void ComposeWidget::changeEvent(QEvent *e)
114 QWidget::changeEvent(e);
115 switch (e->type()) {
116 case QEvent::LanguageChange:
117 ui->retranslateUi(this);
118 break;
119 default:
120 break;
124 bool ComposeWidget::buildMessageData()
126 QList<QPair<RecipientKind,Imap::Message::MailAddress> > recipients;
127 if (!parseRecipients(recipients)) {
128 gotError(tr("Cannot parse recipients"));
129 return false;
131 if (recipients.isEmpty()) {
132 gotError(tr("You haven't entered any recipients"));
133 return false;
135 m_composer->setRecipients(recipients);
137 Imap::Message::MailAddress fromAddress;
138 if (!Imap::Message::MailAddress::fromPrettyString(fromAddress, ui->sender->currentText())) {
139 gotError(tr("The From: address does not look like a valid one"));
140 return false;
142 m_composer->setFrom(fromAddress);
144 m_composer->setTimestamp(QDateTime::currentDateTime());
145 m_composer->setSubject(ui->subject->text());
146 m_composer->setText(ui->mailText->toPlainText());
148 return m_composer->isReadyForSerialization();
151 void ComposeWidget::send()
154 if (!buildMessageData())
155 return;
157 using Common::SettingsNames;
158 QSettings s;
160 QByteArray rawMessageData;
161 QBuffer buf(&rawMessageData);
162 buf.open(QIODevice::WriteOnly);
163 QString errorMessage;
165 QPointer<Imap::Mailbox::AppendTask> appendTask = 0;
166 m_appendUidReceived = false;
167 m_genUrlAuthReceived = false;
168 if (s.value(SettingsNames::composerSaveToImapKey, true).toBool()) {
169 Q_ASSERT(m_mainWindow->imapModel());
171 if (m_mainWindow->isCatenateSupported()) {
172 QList<Imap::Mailbox::CatenatePair> catenateable;
173 if (!m_composer->asCatenateData(catenateable, &errorMessage)) {
174 gotError(tr("Cannot send right now -- saving (CATENATE) failed:\n %1").arg(errorMessage));
175 return;
178 // FIXME: without UIDPLUS, there isn't much point in $SubmitPending...
179 appendTask = QPointer<Imap::Mailbox::AppendTask>(
180 m_mainWindow->imapModel()->appendIntoMailbox(
181 s.value(SettingsNames::composerImapSentKey, tr("Sent")).toString(),
182 catenateable,
183 QStringList() << QLatin1String("$SubmitPending") << QLatin1String("\\Seen"),
184 m_composer->timestamp()));
185 } else {
186 if (!m_composer->asRawMessage(&buf, &errorMessage)) {
187 gotError(tr("Cannot send right now -- saving failed:\n %1").arg(errorMessage));
188 return;
191 // FIXME: without UIDPLUS, there isn't much point in $SubmitPending...
192 appendTask = QPointer<Imap::Mailbox::AppendTask>(
193 m_mainWindow->imapModel()->appendIntoMailbox(
194 s.value(SettingsNames::composerImapSentKey, tr("Sent")).toString(),
195 rawMessageData,
196 QStringList() << QLatin1String("$SubmitPending") << QLatin1String("\\Seen"),
197 m_composer->timestamp()));
200 Q_ASSERT(appendTask);
201 connect(appendTask.data(), SIGNAL(appendUid(uint,uint)), this, SLOT(slotAppendUidKnown(uint,uint)));
204 if (rawMessageData.isEmpty() && shouldBuildMessageLocally()) {
205 if (!m_composer->asRawMessage(&buf, &errorMessage)) {
206 gotError(tr("Cannot send right now:\n %1").arg(errorMessage));
207 return;
211 MSA::AbstractMSA *msa = 0;
212 QString method = s.value(SettingsNames::msaMethodKey).toString();
213 if (method == SettingsNames::methodSMTP || method == SettingsNames::methodSSMTP) {
214 msa = new MSA::SMTP(this, s.value(SettingsNames::smtpHostKey).toString(),
215 s.value(SettingsNames::smtpPortKey).toInt(),
216 (method == SettingsNames::methodSSMTP),
217 (method == SettingsNames::methodSMTP)
218 && s.value(SettingsNames::smtpStartTlsKey).toBool(),
219 s.value(SettingsNames::smtpAuthKey).toBool(),
220 s.value(SettingsNames::smtpUserKey).toString(),
221 s.value(SettingsNames::smtpPassKey).toString());
222 } else if (method == SettingsNames::methodSENDMAIL) {
223 QStringList args = s.value(SettingsNames::sendmailKey, SettingsNames::sendmailDefaultCmd).toString().split(QLatin1Char(' '));
224 if (args.isEmpty()) {
225 QMessageBox::critical(this, tr("Error"), tr("Please configure the SMTP or sendmail settings in application settings."));
226 return;
228 QString appName = args.takeFirst();
229 msa = new MSA::Sendmail(this, appName, args);
230 } else if (method == SettingsNames::methodImapSendmail) {
231 if (!m_mainWindow->isImapSubmissionSupported()) {
232 QMessageBox::critical(this, tr("Error"), tr("The IMAP server does not support mail submission. Please reconfigure the application."));
233 return;
235 // no particular preparation needed here
236 } else {
237 QMessageBox::critical(this, tr("Error"), tr("Please configure e-mail delivery method in application settings."));
238 return;
241 QProgressDialog *progress = new QProgressDialog(
242 tr("Sending mail"), tr("Abort"), 0, rawMessageData.size(), this);
243 progress->setMinimumDuration(0);
244 progress->setMaximum(3);
246 // Message uploading through IMAP cannot really be terminated
247 setEnabled(false);
248 progress->setEnabled(true);
250 if (appendTask) {
251 progress->setLabelText(tr("Saving message..."));
254 while (appendTask && !appendTask->isFinished()) {
255 // FIXME: get rid of this busy wait, eventually
256 QCoreApplication::processEvents();
259 if (method == SettingsNames::methodImapSendmail) {
260 if (!m_appendUidReceived) {
261 QMessageBox::critical(this, tr("Error"), tr("Cannot send over IMAP, APPENDUID failed"));
262 return;
264 Imap::Mailbox::UidSubmitOptionsList options;
265 options.append(qMakePair<QByteArray,QVariant>("FROM", m_composer->rawFromAddress()));
266 Q_FOREACH(const QByteArray &recipient, m_composer->rawRecipientAddresses()) {
267 options.append(qMakePair<QByteArray,QVariant>("RECIPIENT", recipient));
269 Imap::Mailbox::UidSubmitTask *submitTask = m_mainWindow->imapModel()->sendMailViaUidSubmit(
270 s.value(SettingsNames::composerImapSentKey, tr("Sent")).toString(), m_appendUidValidity, m_appendUid,
271 options);
272 Q_ASSERT(submitTask);
273 connect(submitTask, SIGNAL(completed(ImapTask*)), this, SLOT(sent()));
274 connect(submitTask, SIGNAL(failed(QString)), this, SLOT(gotError(QString)));
275 progress->setLabelText(tr("Sending mail..."));
276 progress->setValue(2);
277 while (submitTask && !submitTask->isFinished()) {
278 QCoreApplication::processEvents();
280 progress->cancel();
281 return;
284 QPointer<Imap::Mailbox::GenUrlAuthTask> genUrlAuthTask;
285 if (m_appendUidReceived && s.value(SettingsNames::smtpUseBurlKey, false).toBool() && m_mainWindow->isGenUrlAuthSupported()) {
286 progress->setValue(1);
287 progress->setLabelText(tr("Generating IMAP URL..."));
288 genUrlAuthTask = QPointer<Imap::Mailbox::GenUrlAuthTask>(
289 m_mainWindow->imapModel()->
290 generateUrlAuthForMessage(s.value(SettingsNames::imapHostKey).toString(),
291 killDomainPartFromString(s.value(SettingsNames::imapUserKey).toString()),
292 s.value(SettingsNames::composerImapSentKey, tr("Sent")).toString(),
293 m_appendUidValidity, m_appendUid, QString(),
294 QString::fromUtf8("submit+%1").arg(
295 killDomainPartFromString(s.value(SettingsNames::smtpUserKey).toString()))
297 connect(genUrlAuthTask.data(), SIGNAL(gotAuth(QString)), this, SLOT(slotGenUrlAuthReceived(QString)));
298 while (genUrlAuthTask && !genUrlAuthTask->isFinished()) {
299 // FIXME: get rid of this busy wait, eventually
300 QCoreApplication::processEvents();
303 progress->setLabelText(tr("Sending mail..."));
304 progress->setValue(2);
306 connect(msa, SIGNAL(progressMax(int)), progress, SLOT(setMaximum(int)));
307 connect(msa, SIGNAL(progress(int)), progress, SLOT(setValue(int)));
308 connect(msa, SIGNAL(error(QString)), progress, SLOT(close()));
309 connect(msa, SIGNAL(sent()), progress, SLOT(close()));
310 connect(msa, SIGNAL(sent()), this, SLOT(sent()));
311 connect(msa, SIGNAL(sent()), this, SLOT(deleteLater()));
312 connect(progress, SIGNAL(canceled()), msa, SLOT(cancel()));
313 connect(msa, SIGNAL(error(QString)), this, SLOT(gotError(QString)));
315 if (m_genUrlAuthReceived && s.value(SettingsNames::smtpUseBurlKey, false).toBool()) {
316 msa->sendBurl(m_composer->rawFromAddress(), m_composer->rawRecipientAddresses(), m_urlauth.toUtf8());
317 } else {
318 msa->sendMail(m_composer->rawFromAddress(), m_composer->rawRecipientAddresses(), rawMessageData);
324 void ComposeWidget::setData(const QList<QPair<RecipientKind, QString> > &recipients,
325 const QString &subject, const QString &body, const QList<QByteArray> &inReplyTo,
326 const QList<QByteArray> &references)
328 for (int i = 0; i < recipients.size(); ++i) {
329 addRecipient(i, recipients.at(i).first, recipients.at(i).second);
331 if (recipients.isEmpty())
332 addRecipient(0, Imap::Mailbox::MessageComposer::Recipient_To, QString());
333 else
334 addRecipient(recipients.size(), recipients.last().first, QString());
335 ui->subject->setText(subject);
336 ui->mailText->setText(body);
337 m_composer->setInReplyTo(inReplyTo);
338 m_composer->setReferences(references);
341 //BEGIN QFormLayout workarounds
343 /** First issue: QFormLayout messes up rows by never removing them
344 * ----------------------------------------------------------------
345 * As a result insertRow(int pos, .) does not pick the expected row, but usually minor
346 * (if you ever removed all items of a row in this layout)
348 * Solution: we count all rows non empty rows and when we have enough, return the row suitable for
349 * QFormLayout (which is usually behind the requested one)
351 static int actualRow(QFormLayout *form, int row)
353 for (int i = 0, c = 0; i < form->rowCount(); ++i) {
354 if (c == row) {
355 return i;
357 if (form->itemAt(i, QFormLayout::LabelRole) || form->itemAt(i, QFormLayout::FieldRole) ||
358 form->itemAt(i, QFormLayout::SpanningRole))
359 ++c;
361 return form->rowCount(); // append
364 /** Second (related) issue: QFormLayout messes the tab order
365 * ----------------------------------------------------------
366 * "Inserted" rows just get appended to the present ones and by this to the tab focus order
367 * It's therefore necessary to fix this forcing setTabOrder()
369 * Approach: traverse all rows until we have the widget that shall be inserted in tab order and
370 * return it's predecessor
373 static QWidget* formPredecessor(QFormLayout *form, QWidget *w)
375 QWidget *pred = 0;
376 QWidget *runner = 0;
377 QLayoutItem *item = 0;
378 for (int i = 0; i < form->rowCount(); ++i) {
379 if ((item = form->itemAt(i, QFormLayout::LabelRole))) {
380 runner = item->widget();
381 if (runner == w)
382 return pred;
383 else if (runner)
384 pred = runner;
386 if ((item = form->itemAt(i, QFormLayout::FieldRole))) {
387 runner = item->widget();
388 if (runner == w)
389 return pred;
390 else if (runner)
391 pred = runner;
393 if ((item = form->itemAt(i, QFormLayout::SpanningRole))) {
394 runner = item->widget();
395 if (runner == w)
396 return pred;
397 else if (runner)
398 pred = runner;
401 return pred;
404 //END QFormLayout workarounds
407 void ComposeWidget::addRecipient(int position, RecipientKind kind, const QString &address)
409 QComboBox *combo = new QComboBox(this);
410 combo->addItem(tr("To"), Imap::Mailbox::MessageComposer::Recipient_To);
411 combo->addItem(tr("Cc"), Imap::Mailbox::MessageComposer::Recipient_Cc);
412 combo->addItem(tr("Bcc"), Imap::Mailbox::MessageComposer::Recipient_Bcc);
413 combo->setCurrentIndex(combo->findData(kind));
414 QLineEdit *edit = new QLineEdit(address, this);
415 connect(edit, SIGNAL(textEdited(QString)), SLOT(completeRecipients(QString)));
416 connect(edit, SIGNAL(editingFinished()), SLOT(collapseRecipients()));
417 connect(edit, SIGNAL(textChanged(QString)), m_recipientListUpdateTimer, SLOT(start()));
418 m_recipients.insert(position, Recipient(combo, edit));
419 ui->envelopeLayout->insertRow(actualRow(ui->envelopeLayout, position + OFFSET_OF_FIRST_ADDRESSEE), combo, edit);
420 setTabOrder(formPredecessor(ui->envelopeLayout, combo), combo);
421 setTabOrder(combo, edit);
424 void ComposeWidget::removeRecipient(int pos)
426 // removing the widgets from the layout is important
427 // a) not doing so leaks (minor)
428 // b) deleteLater() crosses the evenchain and so our actualRow funtion would be tricked
429 ui->envelopeLayout->removeWidget(m_recipients.at(pos).first);
430 ui->envelopeLayout->removeWidget(m_recipients.at(pos).second);
431 m_recipients.at(pos).first->deleteLater();
432 m_recipients.at(pos).second->deleteLater();
433 m_recipients.removeAt(pos);
436 static inline ComposeWidget::RecipientKind currentRecipient(const QComboBox *box)
438 return ComposeWidget::RecipientKind(box->itemData(box->currentIndex()).toInt());
441 void ComposeWidget::updateRecipientList()
443 // we ensure there's always one empty available
444 bool haveEmpty = false;
445 for (int i = 0; i < m_recipients.count(); ++i) {
446 if (m_recipients.at(i).second->text().isEmpty()) {
447 if (haveEmpty) {
448 removeRecipient(i);
450 haveEmpty = true;
453 if (!haveEmpty)
454 addRecipient(m_recipients.count(), currentRecipient(m_recipients.last().first), QString());
457 void ComposeWidget::collapseRecipients()
459 QLineEdit *edit = qobject_cast<QLineEdit*>(sender());
460 Q_ASSERT(edit);
461 if (edit->hasFocus() || !edit->text().isEmpty())
462 return; // nothing to clean up
464 // an empty recipient line just lost focus -> we "place it at the end", ie. simply remove it
465 // and append a clone
466 bool needEmpty = false;
467 RecipientKind carriedKind = Imap::Mailbox::MessageComposer::Recipient_To;
468 for (int i = 0; i < m_recipients.count() - 1; ++i) { // sic! on the -1, no action if it trails anyway
469 if (m_recipients.at(i).second == edit) {
470 carriedKind = currentRecipient(m_recipients.last().first);
471 removeRecipient(i);
472 needEmpty = true;
473 break;
476 if (needEmpty)
477 addRecipient(m_recipients.count(), carriedKind, QString());
480 void ComposeWidget::gotError(const QString &error)
482 QMessageBox::critical(this, tr("Failed to Send Mail"), error);
483 setEnabled(true);
486 void ComposeWidget::sent()
488 QMessageBox::information(this, tr("OK"), tr("Message Sent"));
489 setEnabled(true);
492 bool ComposeWidget::parseRecipients(QList<QPair<RecipientKind, Imap::Message::MailAddress> > &results)
494 for (int i = 0; i < m_recipients.size(); ++i) {
495 RecipientKind kind = currentRecipient(m_recipients.at(i).first);
497 int offset = 0;
498 QString text = m_recipients.at(i).second->text();
499 for(;;) {
500 Imap::Message::MailAddress addr;
501 bool ok = Imap::Message::MailAddress::parseOneAddress(addr, text, offset);
502 if (ok) {
503 // TODO: should we *really* learn every junk entered into a recipient field?
504 // m_mainWindow->addressBook()->learn(addr);
505 results << qMakePair(kind, addr);
506 } else if (offset < text.size()) {
507 QMessageBox::critical(this, tr("Invalid Address"),
508 tr("Can't parse \"%1\" as an e-mail address").arg(text.mid(offset)));
509 return false;
510 } else {
511 /* Successfully parsed the field. */
512 break;
516 return true;
519 void ComposeWidget::completeRecipients(const QString &text)
521 if (text.isEmpty()) {
522 if (m_completionPopup) {
523 // if there's a popup close it and set back the receiver
524 m_completionPopup->close();
525 m_completionReceiver = 0;
527 return; // we do not suggest "nothing"
529 Q_ASSERT(sender());
530 QLineEdit *toEdit = static_cast<QLineEdit*>(sender());
531 QStringList contacts = m_mainWindow->addressBook()->complete(text, QStringList(), m_completionCount);
532 if (contacts.isEmpty() && m_completionPopup) {
533 m_completionPopup->close();
534 m_completionReceiver = 0;
536 else {
537 m_completionReceiver = toEdit;
538 m_completionPopup->setUpdatesEnabled(false);
539 m_completionPopup->clear();
540 Q_FOREACH(const QString &s, contacts)
541 m_completionPopup->addAction(s);
542 if (m_completionPopup->isHidden())
543 m_completionPopup->popup(toEdit->mapToGlobal(QPoint(0, toEdit->height())));
544 m_completionPopup->setUpdatesEnabled(true);
548 void ComposeWidget::completeRecipient(QAction *act)
550 if (act->text().isEmpty())
551 return;
552 m_completionReceiver->setText(act->text());
553 if (m_completionPopup) {
554 m_completionPopup->close();
555 m_completionReceiver = 0;
559 bool ComposeWidget::eventFilter(QObject *o, QEvent *e)
561 if (o == m_completionPopup) {
562 if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
563 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
564 if (!( ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down || // Navigation
565 ke->key() == Qt::Key_Escape || // "escape"
566 ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)) { // selection
567 QCoreApplication::sendEvent(m_completionReceiver, e);
568 return true;
571 return false;
573 return false;
577 void ComposeWidget::slotAskForFileAttachment()
579 QString fileName = QFileDialog::getOpenFileName(this, tr("Attach File..."), QString(), QString(), 0,
580 QFileDialog::DontResolveSymlinks);
581 if (!fileName.isEmpty()) {
582 m_composer->addFileAttachment(fileName);
586 void ComposeWidget::slotAttachFiles(QList<QUrl> urls)
588 foreach (const QUrl &url, urls) {
590 #if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
591 if (url.isLocalFile()) {
592 #else
593 if (url.scheme() == QLatin1String("file")) {
594 #endif
595 m_composer->addFileAttachment(url.path());
600 void ComposeWidget::slotRemoveAttachment()
602 m_composer->removeAttachment(ui->attachmentsView->currentIndex());
605 /** @short Remember the APPENDUID as reported by the APPEND operation */
606 void ComposeWidget::slotAppendUidKnown(const uint uidValidity, const uint uid)
608 m_appendUidValidity = uidValidity;
609 m_appendUid = uid;
611 if (m_appendUid && m_appendUidValidity) {
612 // Only ever consider valid UIDVALIDITY/UID pair
613 m_appendUidReceived = true;
617 /** @short Remember the GENURLAUTH response */
618 void ComposeWidget::slotGenUrlAuthReceived(const QString &url)
620 m_urlauth = url;
621 if (!m_urlauth.isEmpty()) {
622 m_genUrlAuthReceived = true;
626 /** @short Remove the "@domain" from a string */
627 QString ComposeWidget::killDomainPartFromString(const QString &s)
629 return s.split(QLatin1Char('@'))[0];
632 /** @short Return true if the message payload shall be built locally */
633 bool ComposeWidget::shouldBuildMessageLocally() const
635 // Unless all of URLAUTH, CATENATE and BURL is present and enabled, we will still have to download the data in the end
636 return ! (m_mainWindow->isCatenateSupported() && m_mainWindow->isGenUrlAuthSupported()
637 && QSettings().value(Common::SettingsNames::smtpUseBurlKey, false).toBool());