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.
 
 
 

316 lines
7.9 KiB

// kmsender.cpp
#include "kmsender.h"
#include "kmfoldermgr.h"
#include "kmmessage.h"
#include "kmglobal.h"
#include "kmfolder.h"
#include "kmidentity.h"
#include <kconfig.h>
#include <kapp.h>
#include <kprocess.h>
#include <klocale.h>
#include <qregexp.h>
#include <assert.h>
#include <stdio.h>
#define SENDER_GROUP "sending mail"
//-----------------------------------------------------------------------------
KMSender::KMSender()
{
mMailerProc = NULL;
readConfig();
}
//-----------------------------------------------------------------------------
KMSender::~KMSender()
{
if (mMailerProc) delete mMailerProc;
writeConfig(TRUE);
}
//-----------------------------------------------------------------------------
void KMSender::readConfig(void)
{
QString str;
KConfig* config = app->getConfig();
config->setGroup(SENDER_GROUP);
mSendImmediate = (bool)config->readNumEntry("Immediate", TRUE);
mMailer = config->readEntry("Mailer", "/usr/sbin/sendmail");
mSmtpHost = config->readEntry("Smtp Host", "localhost");
mSmtpPort = config->readNumEntry("Smtp Port", 25);
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 = app->getConfig();
config->setGroup(SENDER_GROUP);
config->writeEntry("Immediate", mSendImmediate);
config->writeEntry("Mailer", mMailer);
config->writeEntry("Smtp Host", mSmtpHost);
config->writeEntry("Smtp Port", mSmtpPort);
config->writeEntry("Method", (mMethod==smSMTP) ? "smtp" : "mail");
if (aWithSync) config->sync();
}
//-----------------------------------------------------------------------------
bool KMSender::sendQueued(void)
{
KMMessage* msg;
bool rc = TRUE;
outboxFolder->open();
while(outboxFolder->count() > 0)
{
msg = outboxFolder->getMsg(0);
rc = send(msg, TRUE);
if (!rc) break;
}
outboxFolder->close();
return rc;
}
//-----------------------------------------------------------------------------
bool KMSender::send(KMMessage* aMsg, short sendNow)
{
bool sendOk = FALSE;
int rc;
assert(aMsg != NULL);
if (!identity->mailingAllowed())
{
warning(nls->translate("Please set the required fields in the\n"
"identity settings:\n"
"user-name and email-address"));
return FALSE;
}
if (!aMsg->to() || aMsg->to()[0]=='\0') return FALSE;
//aMsg->viewSource("KMSender::send()");
if (sendNow==-1) sendNow = mSendImmediate;
if (!sendNow)
{
rc = outboxFolder->addMsg(aMsg);
if (!rc) aMsg->setStatus(KMMsgStatusQueued);
return (rc==0);
}
if (mMethod == smSMTP) sendOk = sendSMTP(aMsg);
else if (mMethod == smMail) sendOk = sendMail(aMsg);
else warning(nls->translate("Please specify a send\nmethod in the settings\n"
"and try again."));
if (sendOk)
{
aMsg->setStatus(KMMsgStatusSent);
sentFolder->addMsg(aMsg);
}
return sendOk;
}
//-----------------------------------------------------------------------------
bool KMSender::sendSMTP(KMMessage *msg)
{
void (*oldHandler)(int);
bool result;
oldHandler = signal(SIGALRM, SIG_IGN);
result = doSendSMTP(msg);
signal(SIGALRM, oldHandler);
return result;
}
//-----------------------------------------------------------------------------
bool KMSender::doSendSMTP(KMMessage* msg)
{
// $markus: I just could not resist implementing smtp suppport
// This code just must be stable. I checked every darn return code!
// Date: 24. Sept. 97
QString str, msgStr;
int replyCode;
DwSmtpClient client;
assert(msg != NULL);
msgStr = prepareStr(msg->asString(), TRUE);
client.Open(mSmtpHost,mSmtpPort); // Open connection
if(!client.IsOpen) // Check if connection succeded
{
QString str(256);
str.sprintf(nls->translate("Cannot open SMTP connection to\n"
"host %s for sending:\n%s"),
(const char*)mSmtpHost,(const char*)client.Response().c_str());
warning((const char*)str);
return FALSE;
}
app->processEvents(1000);
replyCode = client.Helo(); // Send HELO command
if(replyCode != 250) return smtpFailed(client, "HELO", replyCode);
replyCode = client.Mail(identity->emailAddr());
if(replyCode != 250) return smtpFailed(client, "FROM", replyCode);
replyCode = client.Rcpt(msg->to()); // Send RCPT command
if(replyCode != 250 && replyCode != 251)
return smtpFailed(client, "RCPT", replyCode);
if(!msg->cc().isEmpty()) // Check if cc is set.
{
replyCode = client.Rcpt(msg->cc()); // Send RCPT command
if(replyCode != 250 && replyCode != 251)
return smtpFailed(client, "RCPT", replyCode);
}
if(!msg->bcc().isEmpty()) // Check if bcc ist set.
{
replyCode = client.Rcpt(msg->bcc()); // Send RCPT command
if(replyCode != 250 && replyCode != 251)
return smtpFailed(client, "RCPT", replyCode);
}
app->processEvents(1000);
replyCode = client.Data(); // Send DATA command
if(replyCode != 354)
return smtpFailed(client, "DATA", replyCode);
replyCode = client.SendData((const char*)msgStr);
if(replyCode != 250 && replyCode != 251)
return smtpFailed(client, "<body>", replyCode);
replyCode = client.Quit(); // Send QUIT command
if(replyCode != 221)
return smtpFailed(client, "QUIT", replyCode);
return TRUE;
}
//-----------------------------------------------------------------------------
bool KMSender::smtpFailed(DwSmtpClient& client, const char* inCommand,
int replyCode)
{
QString str(256);
const char* errorStr = client.Response().c_str();
str.sprintf(nls->translate("Failed to send mail message\n"
"because a SMTP error occured\n"
"during the \"%s\" command.\n\n"
"Return code: %d\n"
"Response: `%s'"),
inCommand, replyCode, errorStr ? errorStr : "(NULL)");
warning((const char*)str);
if (replyCode != 0) smtpClose(client);
return FALSE;
}
//-----------------------------------------------------------------------------
void KMSender::smtpClose(DwSmtpClient& client)
{
if (client.Close() != 0)
warning(nls->translate("Cannot close SMTP connection."));
}
//-----------------------------------------------------------------------------
bool KMSender::sendMail(KMMessage* aMsg)
{
QString msgstr;
if (mMailer.isEmpty())
{
warning(nls->translate("Please specify a mailer program\n"
"in the settings."));
return FALSE;
}
msgstr = prepareStr(aMsg->asString());
if (!mMailerProc) mMailerProc = new KProcess;
assert(mMailerProc != NULL);
mMailerProc->clearArguments();
*mMailerProc << aMsg->to();
mMailerProc->setExecutable(mMailer);
mMailerProc->start(KProcess::DontCare, KProcess::Stdin);
if (!mMailerProc->writeStdin(msgstr.data(), msgstr.length()))
return FALSE;
if (!mMailerProc->closeStdin()) return FALSE;
return TRUE;
}
//-----------------------------------------------------------------------------
const QString KMSender::prepareStr(const QString aStr, bool toCRLF)
{
QString str = aStr.copy();
str.replace(QRegExp("\\n\\."), "\n .");
str.replace(QRegExp("\\nFrom "), "\n>From ");
if (toCRLF) str.replace(QRegExp("\\n"), "\r\n");
return str;
}
//-----------------------------------------------------------------------------
void KMSender::setMethod(Method aMethod)
{
mMethod = aMethod;
}
//-----------------------------------------------------------------------------
void KMSender::setSendImmediate(bool aSendImmediate)
{
mSendImmediate = aSendImmediate;
}
//-----------------------------------------------------------------------------
void KMSender::setMailer(const QString& aMailer)
{
mMailer = aMailer;
}
//-----------------------------------------------------------------------------
void KMSender::setSmtpHost(const QString& aSmtpHost)
{
mSmtpHost = aSmtpHost;
}
//-----------------------------------------------------------------------------
void KMSender::setSmtpPort(int aSmtpPort)
{
mSmtpPort = aSmtpPort;
}