You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
975 lines
24 KiB
975 lines
24 KiB
// kmsender.cpp |
|
|
|
|
|
#include "kmfoldermgr.h" |
|
#include "kmglobal.h" |
|
#include "kmfolder.h" |
|
|
|
#include "kmsender.h" |
|
#include "kmmessage.h" |
|
#include "kmidentity.h" |
|
#include "kmiostatusdlg.h" |
|
#include "kbusyptr.h" |
|
#include "kmaccount.h" |
|
#include "smtp.h" |
|
|
|
#include <kdebug.h> |
|
#include <kconfig.h> |
|
#include <kprocess.h> |
|
#include <kapp.h> |
|
#include <kmessagebox.h> |
|
#include <kwin.h> |
|
#include <qregexp.h> |
|
#include <qdialog.h> |
|
|
|
#include <assert.h> |
|
#include <stdio.h> |
|
#include <unistd.h> |
|
#include <fcntl.h> |
|
#include <sys/types.h> |
|
#include <sys/stat.h> |
|
#include <sys/wait.h> |
|
#include <klocale.h> |
|
|
|
#ifdef HAVE_PATHS_H |
|
#include <paths.h> |
|
#endif |
|
|
|
#ifndef _PATH_SENDMAIL |
|
#define _PATH_SENDMAIL "/usr/sbin/sendmail" |
|
#endif |
|
|
|
#define SENDER_GROUP "sending mail" |
|
|
|
//----------------------------------------------------------------------------- |
|
KMSender::KMSender() |
|
{ |
|
mSendDlg = NULL; |
|
mSendProc = NULL; |
|
mMsgSendProc = NULL; |
|
mSendProcStarted = FALSE; |
|
mSendInProgress = FALSE; |
|
mCurrentMsg = NULL; |
|
labelDialog = 0; |
|
readConfig(); |
|
quitOnDone = false; |
|
mSendAborted = false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMSender::~KMSender() |
|
{ |
|
writeConfig(FALSE); |
|
if (mSendProc) delete mSendProc; |
|
if (labelDialog) delete labelDialog; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void |
|
KMSender::setStatusMsg(const QString &msg) |
|
{ |
|
if (labelDialog) |
|
label->setText( msg ); |
|
emit statusMsg( msg); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::readConfig(void) |
|
{ |
|
QString str; |
|
KConfig* config = kapp->config(); |
|
|
|
config->setGroup(SENDER_GROUP); |
|
|
|
mSendImmediate = (bool)config->readNumEntry("Immediate", TRUE); |
|
mSendQuotedPrintable = (bool)config->readNumEntry("Quoted-Printable", FALSE); |
|
mMailer = config->readEntry("Mailer", _PATH_SENDMAIL); |
|
mSmtpHost = config->readEntry("Smtp Host", "localhost"); |
|
mSmtpPort = config->readNumEntry("Smtp Port", 25); |
|
mPrecommand = config->readEntry("Precommand", ""); |
|
|
|
str = config->readEntry("Method"); |
|
if (str=="mail") mMethod = smMail; |
|
else if (str=="smtp") mMethod = smSMTP; |
|
else mMethod = smUnknown; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::writeConfig(bool aWithSync) |
|
{ |
|
KConfig* config = kapp->config(); |
|
config->setGroup(SENDER_GROUP); |
|
|
|
config->writeEntry("Immediate", mSendImmediate); |
|
config->writeEntry("Quoted-Printable", mSendQuotedPrintable); |
|
config->writeEntry("Mailer", mMailer); |
|
config->writeEntry("Smtp Host", mSmtpHost); |
|
config->writeEntry("Smtp Port", (int)mSmtpPort); |
|
config->writeEntry("Method", (mMethod==smSMTP) ? "smtp" : "mail"); |
|
config->writeEntry("Precommand", mPrecommand); |
|
|
|
if (aWithSync) config->sync(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSender::settingsOk(void) const |
|
{ |
|
KMIdentity ident( i18n( "Default" )); |
|
ident.readConfig(); |
|
if (mMethod!=smSMTP && mMethod!=smMail) |
|
{ |
|
KMessageBox::information(0,i18n("Please specify a send\n" |
|
"method in the settings\n" |
|
"and try again.")); |
|
return FALSE; |
|
} |
|
if (!ident.mailingAllowed()) |
|
{ |
|
KMessageBox::information(0,i18n("Please set the required fields in the\n" |
|
"identity settings:\n" |
|
"user-name and email-address")); |
|
return FALSE; |
|
} |
|
return TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSender::send(KMMessage* aMsg, short sendNow) |
|
{ |
|
int rc; |
|
|
|
//assert(aMsg != NULL); |
|
if(!aMsg) |
|
{ |
|
return false; |
|
} |
|
if (!settingsOk()) return FALSE; |
|
|
|
if (aMsg->to().isEmpty()) |
|
{ |
|
// RFC822 says: |
|
// Note that the "Bcc" field may be empty, while the "To" field is required to |
|
// have at least one address. |
|
kernel->kbp()->idle(); |
|
KMessageBox::information(0,i18n("You must specify at least one receiver in the To: field.")); |
|
return FALSE; |
|
} |
|
|
|
if (aMsg->subject().isEmpty()) |
|
{ |
|
kernel->kbp()->idle(); |
|
int rc = KMessageBox::questionYesNo(0, i18n("You did not specify a subject. Send message anyway?"), |
|
i18n("No subject specified"), i18n("Yes"), i18n("No, let me specify the subject")); |
|
if( rc == KMessageBox::No ) { |
|
return FALSE; |
|
} |
|
kernel->kbp()->busy(); |
|
} |
|
|
|
if (sendNow==-1) sendNow = mSendImmediate; |
|
|
|
kernel->outboxFolder()->open(); |
|
aMsg->setStatus(KMMsgStatusQueued); |
|
|
|
// Handle redirections |
|
QString f = aMsg->headerField("X-KMail-Redirect-From"); |
|
if(f.length() > 0) { |
|
QString idStr = aMsg->headerField("X-KMail-Identity"); |
|
KMIdentity ident( idStr.isEmpty() ? i18n( "Default" ) : idStr ); |
|
ident.readConfig(); |
|
|
|
aMsg->setFrom(f + QString(" (by way of %1 <%2>)"). |
|
arg(ident.fullName()).arg(ident.emailAddr())); |
|
} |
|
|
|
rc = kernel->outboxFolder()->addMsg(aMsg); |
|
if (rc) |
|
{ |
|
KMessageBox::information(0,i18n("Cannot add message to outbox folder")); |
|
return FALSE; |
|
} |
|
|
|
if (sendNow && !mSendInProgress) rc = sendQueued(); |
|
else rc = TRUE; |
|
kernel->outboxFolder()->close(); |
|
|
|
return rc; |
|
} |
|
|
|
|
|
bool KMSender::sendSingleMail( KMMessage*) |
|
{ |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSender::sendQueued(void) |
|
{ |
|
if (!settingsOk()) return FALSE; |
|
|
|
if (mSendInProgress) |
|
{ |
|
KMessageBox::information(0,i18n("Sending still in progress")); |
|
return FALSE; |
|
} |
|
|
|
|
|
// open necessary folders |
|
kernel->outboxFolder()->open(); |
|
mCurrentMsg = NULL; |
|
|
|
kernel->sentFolder()->open(); |
|
|
|
|
|
// create a sender |
|
if (mSendProc) delete mSendProc; |
|
if (mMethod == smMail) mSendProc = new KMSendSendmail(this,mMailer); |
|
else if (mMethod == smSMTP) mSendProc = new KMSendSMTP(this,mSmtpHost,mSmtpPort); |
|
else mSendProc = NULL; |
|
assert(mSendProc != NULL); |
|
connect(mSendProc,SIGNAL(idle()),SLOT(slotIdle())); |
|
connect(mSendProc,SIGNAL(started(bool)),this,SLOT(sendProcStarted(bool))); |
|
|
|
// start sending the messages |
|
doSendMsg(); |
|
return TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::doSendMsg() |
|
{ |
|
assert(mSendProc != NULL); |
|
bool someSent = mCurrentMsg; |
|
|
|
// Move previously sent message to folder "sent" |
|
if (mCurrentMsg) |
|
{ |
|
mCurrentMsg->setTransferInProgress( FALSE ); |
|
mCurrentMsg->setStatus(KMMsgStatusSent); |
|
kernel->sentFolder()->moveMsg(mCurrentMsg); |
|
mCurrentMsg = NULL; |
|
} |
|
|
|
// If we have been using a message specific transport, lose it now. |
|
// Would be more efficient to only do this when the mail transport |
|
// (server or port) has changed |
|
if (mMsgSendProc) { |
|
mMsgSendProc->finish(true); |
|
mMsgSendProc = 0; |
|
mSendProcStarted = FALSE; |
|
} |
|
|
|
// See if there is another queued message |
|
mCurrentMsg = kernel->outboxFolder()->getMsg(0); |
|
if (!mCurrentMsg) |
|
{ |
|
// no more message: cleanup and done |
|
cleanup(); |
|
if (someSent) |
|
setStatusMsg(i18n("Queued messages successfully sent.")); |
|
return; |
|
} |
|
mCurrentMsg->setTransferInProgress( TRUE ); |
|
|
|
// start the sender process or initialize communication |
|
if (!mSendProcStarted) |
|
{ |
|
kernel->serverReady (false); //sven - stop IPC |
|
|
|
if (!labelDialog) { |
|
labelDialog = new QDialog(0, "sendinglabel", false, WDestructiveClose ); |
|
label = new QLabel(labelDialog); |
|
labelDialog->setCaption("KMail"); |
|
KWin::setIcons( labelDialog->winId(), kapp->icon(), kapp->miniIcon() ); |
|
connect(labelDialog,SIGNAL(destroyed()),this,SLOT(slotAbortSend())); |
|
label->resize(400, label->sizeHint().height()); |
|
label->setText(i18n("Initiating sender process...")); |
|
labelDialog->show(); |
|
} |
|
|
|
// Run the precommand if there is one |
|
setStatusMsg(i18n("Executing precommand %1").arg(mPrecommand)); |
|
if (!KMAccount::runPrecommand(mPrecommand)) |
|
{ |
|
KMessageBox::error(0, i18n("Couldn't execute precommand:\n%1") |
|
.arg(mPrecommand)); |
|
} |
|
|
|
setStatusMsg(i18n("Initiating sender process...")); |
|
} |
|
|
|
mMethodStr = transportString(); |
|
|
|
QString msgTransport = mCurrentMsg->headerField("X-KMail-Transport"); |
|
if (!msgTransport.isEmpty() && (msgTransport != mMethodStr)) { |
|
if (mSendProcStarted && mSendProc) { |
|
mSendProc->finish(false); |
|
mSendProcStarted = FALSE; |
|
} |
|
|
|
mMsgSendProc = createSendProcFromString(mCurrentMsg->headerField("X-KMail-Transport")); |
|
mMethodStr = msgTransport; |
|
|
|
if (!mMsgSendProc) |
|
msgSendProcStarted(false); |
|
else { |
|
connect(mMsgSendProc,SIGNAL(idle()),SLOT(slotIdle())); |
|
connect(mMsgSendProc,SIGNAL(started(bool)),this,SLOT(msgSendProcStarted(bool))); |
|
mMsgSendProc->start(); |
|
} |
|
} |
|
else if (!mSendProcStarted) |
|
mSendProc->start(); |
|
else |
|
doSendMsgAux(); |
|
} |
|
|
|
void KMSender::msgSendProcStarted(bool success) |
|
{ |
|
if (!success) { |
|
if (mMsgSendProc) |
|
mMsgSendProc->finish(true); |
|
else |
|
setStatusMsg(i18n("Unrecognised transport protocol, could not send message.")); |
|
mMsgSendProc = 0; |
|
mSendProcStarted = false; |
|
cleanup(); |
|
return; |
|
} |
|
doSendMsgAux(); |
|
} |
|
|
|
void KMSender::sendProcStarted(bool success) |
|
{ |
|
if (!success) { |
|
cleanup(); |
|
return; |
|
} |
|
doSendMsgAux(); |
|
} |
|
|
|
void KMSender::doSendMsgAux() |
|
{ |
|
mSendProcStarted = TRUE; |
|
mSendInProgress = TRUE; |
|
|
|
// remove header fields that shall not be included in sending |
|
mCurrentMsg->removeHeaderField("Status"); |
|
mCurrentMsg->removeHeaderField("X-Status"); |
|
mCurrentMsg->removeHeaderField("X-KMail-Transport"); |
|
|
|
// start sending the current message |
|
|
|
if (mMsgSendProc) { |
|
mMsgSendProc->preSendInit(); |
|
setStatusMsg(i18n("Sending message: %1").arg(mCurrentMsg->subject())); |
|
if (!mMsgSendProc->send(mCurrentMsg)) |
|
{ |
|
cleanup(); |
|
setStatusMsg(i18n("Failed to send (some) queued messages.")); |
|
return; |
|
} |
|
} else { |
|
mSendProc->preSendInit(); |
|
setStatusMsg(i18n("Sending message: %1").arg(mCurrentMsg->subject())); |
|
if (!mSendProc->send(mCurrentMsg)) |
|
{ |
|
cleanup(); |
|
setStatusMsg(i18n("Failed to send (some) queued messages.")); |
|
return; |
|
} |
|
} |
|
// Do *not* add code here, after send(). It can happen that this method |
|
// is called recursively if send() emits the idle signal directly. |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::cleanup(void) |
|
{ |
|
assert(mSendProc!=NULL); |
|
|
|
if (mSendProcStarted) mSendProc->finish(false); |
|
mSendProcStarted = FALSE; |
|
mSendInProgress = FALSE; |
|
if (mCurrentMsg) |
|
{ |
|
mCurrentMsg->setTransferInProgress( FALSE ); |
|
mCurrentMsg = NULL; |
|
} |
|
kernel->sentFolder()->close(); |
|
kernel->outboxFolder()->close(); |
|
if (kernel->outboxFolder()->count()<0) |
|
kernel->outboxFolder()->expunge(); |
|
else kernel->outboxFolder()->compact(); |
|
|
|
kernel->serverReady (true); // sven - enable ipc |
|
mSendAborted = false; |
|
if (labelDialog) { |
|
disconnect(labelDialog,SIGNAL(destroyed()),this,SLOT(slotAbortSend())); |
|
delete labelDialog; |
|
labelDialog = 0; |
|
// labelDialog->hide(); |
|
} |
|
if (quitOnDone) |
|
{ |
|
kapp->quit(); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::quitWhenFinished() |
|
{ |
|
quitOnDone=true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::slotAbortSend() |
|
{ |
|
labelDialog = 0; |
|
mSendAborted = true; |
|
if (mMsgSendProc) |
|
mMsgSendProc->abort(); |
|
else |
|
mSendProc->abort(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::slotIdle() |
|
{ |
|
assert(mSendProc != NULL); |
|
|
|
if (!mSendAborted) { |
|
if (mMsgSendProc) { |
|
if (mMsgSendProc->sendOk()) { |
|
doSendMsg(); |
|
return; |
|
} |
|
} else if (mSendProc->sendOk()) { |
|
// sending succeeded |
|
doSendMsg(); |
|
return; |
|
} |
|
} |
|
|
|
// sending of message failed |
|
QString msg; |
|
QString errString; |
|
if (mMsgSendProc) |
|
errString = mMsgSendProc->message(); |
|
else |
|
errString = mSendProc->message(); |
|
|
|
msg = i18n("Sending failed:\n%1\n" |
|
"The message will stay in the 'outbox' folder until you either\n" |
|
"fix the problem (e.g. a broken address) or remove the message\n" |
|
"from the 'outbox' folder.\n\n" |
|
"Note: other messages will also be blocked by this message, as\n" |
|
"long as it is in the 'outbox' folder\n\n" |
|
"The following transport protocol was used:\n %2") |
|
.arg(errString) |
|
.arg(mMethodStr); |
|
KMessageBox::error(0,msg); |
|
|
|
if (mMsgSendProc) { |
|
mMsgSendProc->finish(true); |
|
mMsgSendProc = 0; |
|
mSendProcStarted = false; |
|
} |
|
cleanup(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::setMethod(Method aMethod) |
|
{ |
|
mMethod = aMethod; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::setSendImmediate(bool aSendImmediate) |
|
{ |
|
mSendImmediate = aSendImmediate; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::setSendQuotedPrintable(bool aSendQuotedPrintable) |
|
{ |
|
mSendQuotedPrintable = aSendQuotedPrintable; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::setMailer(const QString& aMailer) |
|
{ |
|
mMailer = aMailer; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::setSmtpHost(const QString& aSmtpHost) |
|
{ |
|
mSmtpHost = aSmtpHost; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSender::setSmtpPort(unsigned short int aSmtpPort) |
|
{ |
|
mSmtpPort = aSmtpPort; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMSendProc* KMSender::createSendProcFromString(QString transport) |
|
{ |
|
if (transport.left(7) == "smtp://") { // to i18n or not to i18n? |
|
QString serverport = transport.mid(7); |
|
QString server = serverport; |
|
QString port = "25"; |
|
int colon = serverport.find(":"); |
|
if (colon != -1) { |
|
server = serverport.left(colon); |
|
port = serverport.mid(colon + 1); |
|
} |
|
return new KMSendSMTP(this,server,port.toInt()); |
|
} |
|
else if (transport.left(7) == "file://") { |
|
return new KMSendSendmail(this,transport.mid(7)); |
|
} |
|
else { |
|
return 0; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
QString KMSender::transportString(void) const |
|
{ |
|
if (mMethod == smSMTP) |
|
return QString("smtp://%1:%2").arg(mSmtpHost).arg(mSmtpPort); |
|
else if (mMethod == smMail) |
|
return QString("file://%1").arg(mMailer); |
|
else |
|
return ""; |
|
} |
|
|
|
|
|
|
|
//============================================================================= |
|
//============================================================================= |
|
KMSendProc::KMSendProc(KMSender* aSender): QObject() |
|
{ |
|
initMetaObject(); |
|
mSender = aSender; |
|
preSendInit(); |
|
mMsg = i18n("operation aborted by user."); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendProc::preSendInit(void) |
|
{ |
|
mSending = FALSE; |
|
mSendOk = FALSE; |
|
mMsg = QString::null; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendProc::failed(const QString &aMsg) |
|
{ |
|
mSending = FALSE; |
|
mSendOk = FALSE; |
|
mMsg = aMsg; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendProc::start(void) |
|
{ |
|
emit started(true); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendProc::finish(bool destructive) |
|
{ |
|
if (destructive) |
|
delete this; |
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
QString KMSendProc::prepareStr(const QString &aStr, bool toCRLF, |
|
bool noSingleDot) |
|
{ |
|
QString str; |
|
int pos=0; |
|
|
|
if (aStr.isEmpty()) return str; |
|
|
|
// Convert LF to CR+LF and handle dots at beginning of line. |
|
for (pos=0; pos<(int)aStr.length(); pos++) |
|
{ |
|
QChar c = aStr[pos]; |
|
if (c=='\n') |
|
{ |
|
if (toCRLF) str += '\r'; |
|
str += c; |
|
|
|
if (noSingleDot && aStr[pos+1]=='.') |
|
{ |
|
pos++; |
|
str += ".."; |
|
} |
|
} |
|
else str += c; |
|
} |
|
|
|
return str; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendProc::statusMsg(const QString& aMsg) |
|
{ |
|
if (mSender) mSender->setStatusMsg(aMsg); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendProc::addRecipients(const QStrList& aRecipientList) |
|
{ |
|
QStrList* recpList = (QStrList*)&aRecipientList; |
|
QString receiver; |
|
int i, j; |
|
bool rc; |
|
|
|
for (receiver=recpList->first(); !receiver.isNull(); receiver=recpList->next()) |
|
{ |
|
i = receiver.find('<'); |
|
if (i >= 0) |
|
{ |
|
j = receiver.find('>', i+1); |
|
if (j > i) receiver = receiver.mid(i+1, j-i-1); |
|
} |
|
else // if it's "radej@kde.org (Sven Radej)" |
|
{ |
|
i=receiver.find('('); |
|
if (i > 0) |
|
receiver.truncate(i); // "radej@kde.org " |
|
} |
|
//printf ("Receiver = %s\n", receiver.data()); |
|
|
|
receiver = receiver.stripWhiteSpace(); |
|
if (!receiver.isEmpty()) |
|
{ |
|
rc = addOneRecipient(receiver); |
|
if (!rc) return FALSE; |
|
} |
|
} |
|
return TRUE; |
|
} |
|
|
|
|
|
//============================================================================= |
|
//============================================================================= |
|
KMSendSendmail::KMSendSendmail(KMSender* aSender, QString mailer): |
|
KMSendSendmailInherited(aSender), mMailer(mailer) |
|
{ |
|
initMetaObject(); |
|
mMailerProc = NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
KMSendSendmail::~KMSendSendmail() |
|
{ |
|
if (mMailerProc) delete mMailerProc; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSendmail::start(void) |
|
{ |
|
if (mMailer.isEmpty()) |
|
{ |
|
QString str = i18n("Please specify a mailer program\n" |
|
"in the settings."); |
|
QString msg; |
|
msg = i18n("Sending failed:\n%1\n" |
|
"The message will stay in the 'outbox' folder and will be resent.\n" |
|
"Please remove it from there if you do not want the message to\n" |
|
"be resent.\n\n" |
|
"The following transport protocol was used:\n %2") |
|
.arg(str + "\n") |
|
.arg("sendmail://"); |
|
KMessageBox::information(0,msg); |
|
emit started(false); |
|
} |
|
|
|
if (!mMailerProc) |
|
{ |
|
mMailerProc = new KProcess; |
|
assert(mMailerProc != NULL); |
|
connect(mMailerProc,SIGNAL(processExited(KProcess*)), |
|
this, SLOT(sendmailExited(KProcess*))); |
|
connect(mMailerProc,SIGNAL(wroteStdin(KProcess*)), |
|
this, SLOT(wroteStdin(KProcess*))); |
|
connect(mMailerProc,SIGNAL(receivedStderr(KProcess*,char*,int)), |
|
this, SLOT(receivedStderr(KProcess*, char*, int))); |
|
} |
|
emit started(true); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendSendmail::finish(bool destructive) |
|
{ |
|
if (mMailerProc) delete mMailerProc; |
|
mMailerProc = NULL; |
|
if (destructive) |
|
delete this; |
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSendmail::abort() |
|
{ |
|
if (mMailerProc) delete mMailerProc; |
|
mMailerProc = NULL; |
|
mSendOk = false; |
|
mMsgStr = 0; |
|
idle(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendSendmail::send(KMMessage* aMsg) |
|
{ |
|
QString bccStr; |
|
|
|
mMailerProc->clearArguments(); |
|
*mMailerProc << mMailer; |
|
aMsg->removeHeaderField("X-KMail-Identity"); |
|
addRecipients(aMsg->headerAddrField("To")); |
|
if (!aMsg->cc().isEmpty()) addRecipients(aMsg->headerAddrField("Cc")); |
|
|
|
bccStr = aMsg->bcc(); |
|
if (!bccStr.isEmpty()) |
|
{ |
|
addRecipients(aMsg->headerAddrField("Bcc")); |
|
aMsg->removeHeaderField("Bcc"); |
|
} |
|
|
|
mMsgStr = prepareStr(aMsg->asString()); |
|
if (!bccStr.isEmpty()) aMsg->setBcc(bccStr); |
|
|
|
if (!mMailerProc->start(KProcess::NotifyOnExit,KProcess::All)) |
|
{ |
|
KMessageBox::information(0,i18n("Failed to execute mailer program") + |
|
mMailer); |
|
return FALSE; |
|
} |
|
mMsgPos = mMsgStr.data(); |
|
mMsgRest = mMsgStr.length(); |
|
wroteStdin(mMailerProc); |
|
|
|
return TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSendmail::wroteStdin(KProcess *proc) |
|
{ |
|
char* str; |
|
int len; |
|
|
|
assert(proc!=NULL); |
|
|
|
str = mMsgPos; |
|
len = (mMsgRest>1024 ? 1024 : mMsgRest); |
|
|
|
if (len <= 0) |
|
{ |
|
mMailerProc->closeStdin(); |
|
} |
|
else |
|
{ |
|
mMsgRest -= len; |
|
mMsgPos += len; |
|
mMailerProc->writeStdin(str,len); |
|
// if code is added after writeStdin() KProcess probably initiates |
|
// a race condition. |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSendmail::receivedStderr(KProcess *proc, char *buffer, int buflen) |
|
{ |
|
assert(proc!=NULL); |
|
mMsg.replace(mMsg.length(), buflen, buffer); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSendmail::sendmailExited(KProcess *proc) |
|
{ |
|
assert(proc!=NULL); |
|
mSendOk = (proc->normalExit() && proc->exitStatus()==0); |
|
mMsgStr = 0; |
|
emit idle(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendSendmail::addOneRecipient(const QString &aRcpt) |
|
{ |
|
assert(mMailerProc!=NULL); |
|
if (!aRcpt.isEmpty()) *mMailerProc << aRcpt; |
|
return TRUE; |
|
} |
|
|
|
|
|
//============================================================================= |
|
//============================================================================= |
|
KMSendSMTP::KMSendSMTP(KMSender* aSender, QString smtpHost, |
|
unsigned short int smtpPort ): |
|
KMSendSMTPInherited(aSender), mSmtpHost(smtpHost), mSmtpPort(smtpPort) |
|
{ |
|
smtp = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
KMSendSMTP::~KMSendSMTP() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSMTP::start(void) |
|
{ |
|
statusMsg(i18n("connecting to server")); |
|
emit started(true); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendSMTP::finish(bool destructive) |
|
{ |
|
if (smtp) { |
|
disconnect( smtp, SIGNAL(error(const QString&, const QString&)), |
|
this, SLOT(smtpFailed(const QString&, const QString& )) ); |
|
disconnect( smtp, SIGNAL(success()), |
|
this, SIGNAL(idle()) ); |
|
smtp->quit(); |
|
} |
|
smtp = 0; |
|
if (destructive) |
|
delete this; |
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSMTP::abort() |
|
{ |
|
if (smtp) { |
|
disconnect( smtp, SIGNAL(error(const QString&, const QString&)), |
|
this, SLOT(smtpFailed(const QString&, const QString& )) ); |
|
disconnect( smtp, SIGNAL(success()), |
|
this, SIGNAL(idle()) ); |
|
smtp->quit(); |
|
} |
|
smtp = 0; |
|
idle(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendSMTP::send(KMMessage *msg) |
|
{ |
|
mSendOk = smtpSend(msg); |
|
return mSendOk; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendSMTP::smtpSend(KMMessage* aMsg) |
|
{ |
|
QString str, msgStr, bccStr; |
|
QString idStr = aMsg->headerField("X-KMail-Identity"); |
|
aMsg->removeHeaderField("X-KMail-Identity"); |
|
KMIdentity ident( idStr.isEmpty() ? i18n( "Default" ) : idStr ); |
|
ident.readConfig(); |
|
|
|
assert(aMsg != NULL); |
|
recipients.clear(); |
|
|
|
if (!addRecipients(aMsg->headerAddrField("To"))) return FALSE; |
|
|
|
if (!aMsg->cc().isEmpty()) |
|
if (!addRecipients(aMsg->headerAddrField("Cc"))) return FALSE; |
|
|
|
bccStr = aMsg->bcc(); |
|
if (!bccStr.isEmpty()) |
|
{ |
|
if (!addRecipients(aMsg->headerAddrField("Bcc"))) return FALSE; |
|
aMsg->removeHeaderField("Bcc"); |
|
} |
|
|
|
msgStr = prepareStr(aMsg->asString(), TRUE ); |
|
if (!smtp) { |
|
smtp = new Smtp( ident.emailAddr(), recipients, |
|
msgStr, |
|
mSmtpHost, |
|
mSmtpPort ); |
|
connect( smtp, SIGNAL(error(const QString&, const QString&)), |
|
this, SLOT(smtpFailed(const QString&, const QString& )) ); |
|
connect( smtp, SIGNAL(success()), |
|
this, SIGNAL(idle()) ); |
|
} else { |
|
smtp->send( ident.emailAddr(), recipients, msgStr ); |
|
} |
|
|
|
if (!bccStr.isEmpty()) aMsg->setBcc(bccStr); |
|
return TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMSendSMTP::addOneRecipient(const QString &aRcpt) |
|
{ |
|
if (aRcpt.isEmpty()) return TRUE; |
|
|
|
recipients.append( aRcpt ); |
|
return TRUE; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSMTP::smtpFailed(const QString &command, |
|
const QString &response) |
|
{ |
|
failed( i18n("a SMTP error occured.\n" |
|
"Command: %1\n" |
|
"Response: %2") |
|
.arg(command) |
|
.arg(response) ); |
|
if (smtp) |
|
delete smtp; |
|
smtp = 0; |
|
idle(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMSendSMTP::smtpInCmd(const char* inCommand) |
|
{ |
|
QString str; |
|
str = i18n("Sending SMTP command: %1").arg(inCommand); |
|
statusMsg(str); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
#include "kmsender.moc"
|
|
|