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/>.
23 #include <QFileDialog>
26 #include <QMessageBox>
27 #include <QProgressDialog>
28 #include <QPushButton>
31 #include "AbstractAddressbook.h"
32 #include "AutoCompletion.h"
33 #include "ComposeWidget.h"
34 #include "FromAddressProxyModel.h"
36 #include "ui_ComposeWidget.h"
38 #include "Composer/SenderIdentitiesModel.h"
39 #include "Common/SettingsNames.h"
40 #include "MSA/Sendmail.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"
49 enum { OFFSET_OF_FIRST_ADDRESSEE
= 1 };
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),
61 Q_ASSERT(m_mainWindow
);
62 m_composer
= new Imap::Mailbox::MessageComposer(m_mainWindow
->imapModel(), this);
63 m_composer
->setPreloadEnabled(shouldBuildMessageLocally());
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()
112 void ComposeWidget::changeEvent(QEvent
*e
)
114 QWidget::changeEvent(e
);
116 case QEvent::LanguageChange
:
117 ui
->retranslateUi(this);
124 bool ComposeWidget::buildMessageData()
126 QList
<QPair
<RecipientKind
,Imap::Message::MailAddress
> > recipients
;
127 if (!parseRecipients(recipients
)) {
128 gotError(tr("Cannot parse recipients"));
131 if (recipients
.isEmpty()) {
132 gotError(tr("You haven't entered any recipients"));
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"));
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())
157 using Common::SettingsNames
;
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
));
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(),
183 QStringList() << QLatin1String("$SubmitPending") << QLatin1String("\\Seen"),
184 m_composer
->timestamp()));
186 if (!m_composer
->asRawMessage(&buf
, &errorMessage
)) {
187 gotError(tr("Cannot send right now -- saving failed:\n %1").arg(errorMessage
));
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(),
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
));
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."));
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."));
235 // no particular preparation needed here
237 QMessageBox::critical(this, tr("Error"), tr("Please configure e-mail delivery method in application settings."));
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
248 progress
->setEnabled(true);
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"));
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
,
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();
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());
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());
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
) {
357 if (form
->itemAt(i
, QFormLayout::LabelRole
) || form
->itemAt(i
, QFormLayout::FieldRole
) ||
358 form
->itemAt(i
, QFormLayout::SpanningRole
))
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
)
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();
386 if ((item
= form
->itemAt(i
, QFormLayout::FieldRole
))) {
387 runner
= item
->widget();
393 if ((item
= form
->itemAt(i
, QFormLayout::SpanningRole
))) {
394 runner
= item
->widget();
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()) {
454 addRecipient(m_recipients
.count(), currentRecipient(m_recipients
.last().first
), QString());
457 void ComposeWidget::collapseRecipients()
459 QLineEdit
*edit
= qobject_cast
<QLineEdit
*>(sender());
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
);
477 addRecipient(m_recipients
.count(), carriedKind
, QString());
480 void ComposeWidget::gotError(const QString
&error
)
482 QMessageBox::critical(this, tr("Failed to Send Mail"), error
);
486 void ComposeWidget::sent()
488 QMessageBox::information(this, tr("OK"), tr("Message Sent"));
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
);
498 QString text
= m_recipients
.at(i
).second
->text();
500 Imap::Message::MailAddress addr
;
501 bool ok
= Imap::Message::MailAddress::parseOneAddress(addr
, text
, offset
);
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
)));
511 /* Successfully parsed the field. */
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"
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;
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())
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
);
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()) {
593 if (url
.scheme() == QLatin1String("file")) {
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
;
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
)
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());