~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kscd/smtp.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Kscd - A simple cd player for the KDE Project
 
3
 *
 
4
 * $Id: smtp.cpp,v 1.14 2001/06/10 12:45:37 dfoerste Exp $
 
5
 *
 
6
 * Copyright (c) 1997 Bernd Johannes wuebben@math.cornell.edu
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2, or (at your option)
 
11
 * any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 *
 
22
 */
 
23
 
 
24
#include <smtp.h>
 
25
 
 
26
#include <sys/utsname.h>
 
27
#include <unistd.h>
 
28
#include <stdio.h>
 
29
 
 
30
#include <kdebug.h>
 
31
 
 
32
SMTP::SMTP(char *serverhost, unsigned short int port, int timeout)
 
33
{
 
34
    struct utsname uts;
 
35
 
 
36
    serverHost = serverhost;
 
37
    hostPort = port;
 
38
    timeOut = timeout * 1000;
 
39
 
 
40
    // The following defaults are supposed to be overwritten
 
41
    senderAddress = "user@host.ext";
 
42
    senderReplyTo = "";
 
43
    recipientAddress = "user@host.ext";
 
44
    messageSubject = "freedb unknown unknown";
 
45
    messageBody = "empty";
 
46
    
 
47
    connected = false;
 
48
    finished = false;
 
49
 
 
50
    sock = 0L;
 
51
    state = INIT;
 
52
    serverState = NONE;
 
53
 
 
54
    uname(&uts);
 
55
    domainName = uts.nodename;
 
56
    
 
57
    
 
58
    // this is for the HELO
 
59
    if(domainName.isEmpty())
 
60
        domainName = "somemachine.nowhere.org";
 
61
 
 
62
    connect(&connectTimer, SIGNAL(timeout()), this, SLOT(connectTimerTick()));
 
63
    connect(&timeOutTimer, SIGNAL(timeout()), this, SLOT(connectTimedOut()));
 
64
    connect(&interactTimer, SIGNAL(timeout()), this, SLOT(interactTimedOut()));
 
65
 
 
66
    // some sendmail will give 'duplicate helo' error, quick fix for now
 
67
    connect(this, SIGNAL(messageSent()), SLOT(closeConnection()));
 
68
}
 
69
 
 
70
SMTP::~SMTP()
 
71
{
 
72
    if(sock){
 
73
        delete sock;
 
74
        sock = 0L;
 
75
    }
 
76
    connectTimer.stop();
 
77
    timeOutTimer.stop();
 
78
}
 
79
 
 
80
void SMTP::setServerHost(const QString& serverhost)
 
81
{
 
82
    serverHost = serverhost;
 
83
}
 
84
 
 
85
void SMTP::setPort(unsigned short int port)
 
86
{
 
87
    hostPort = port;
 
88
}
 
89
 
 
90
void SMTP::setTimeOut(int timeout)
 
91
{
 
92
    timeOut = timeout;
 
93
}
 
94
 
 
95
void SMTP::setSenderAddress(const QString& sender)
 
96
{
 
97
    senderAddress = sender;
 
98
}
 
99
 
 
100
void SMTP::setSenderReplyTo(const QString& replyto)
 
101
{
 
102
    senderReplyTo = replyto;
 
103
}
 
104
 
 
105
void SMTP::setRecipientAddress(const QString& recipient)
 
106
{
 
107
    recipientAddress = recipient;
 
108
}
 
109
 
 
110
void SMTP::setMessageSubject(const QString& subject)
 
111
{
 
112
    messageSubject = subject;
 
113
}
 
114
 
 
115
void SMTP::setMessageBody(const QString& message)
 
116
{
 
117
    messageBody = message;
 
118
}
 
119
 
 
120
void SMTP::openConnection(void)
 
121
{
 
122
    kdDebug() << "started connect timer\n" << endl;
 
123
    connectTimer.start(100, TRUE);
 
124
}
 
125
 
 
126
void SMTP::closeConnection(void)
 
127
{
 
128
    socketClose(sock);
 
129
}
 
130
 
 
131
void SMTP::sendMessage(void)
 
132
{
 
133
    if(!connected)
 
134
        connectTimerTick();
 
135
    if(state == FINISHED && connected){
 
136
        kdDebug() << "state was == FINISHED\n" << endl;
 
137
        finished = false;
 
138
        state = IN;
 
139
        writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
 
140
        write(sock->socket(), writeString.ascii(), writeString.length());
 
141
    }
 
142
    if(connected){
 
143
        kdDebug() << "enabling read on sock...\n" << endl;
 
144
        interactTimer.start(timeOut, TRUE);
 
145
        sock->enableRead(true);
 
146
    }
 
147
}
 
148
#include <stdio.h>
 
149
 
 
150
void SMTP::connectTimerTick(void)
 
151
{
 
152
    connectTimer.stop();
 
153
//    timeOutTimer.start(timeOut, TRUE);
 
154
 
 
155
    kdDebug() << "connectTimerTick called...\n" << endl;
 
156
    
 
157
    if(sock){
 
158
        delete sock;
 
159
        sock = 0L;
 
160
    }
 
161
 
 
162
    kdDebug() << "connecting to " << serverHost << ":" << hostPort << " ..... \n" << endl;
 
163
    sock = new KSocket(serverHost.ascii(), hostPort);
 
164
 
 
165
    if(sock == 0L || sock->socket() < 0){
 
166
        timeOutTimer.stop();
 
167
        kdDebug() << "connection failed!\n" << endl;
 
168
        emit error(CONNECTERROR);
 
169
        connected = false;
 
170
        return;
 
171
    }
 
172
    connected = true;
 
173
    finished = false;
 
174
    state = INIT;
 
175
    serverState = NONE;
 
176
 
 
177
    connect(sock, SIGNAL(readEvent(KSocket *)), this, SLOT(socketRead(KSocket *)));
 
178
    connect(sock, SIGNAL(closeEvent(KSocket *)), this, SLOT(socketClose(KSocket *)));
 
179
    //    sock->enableRead(true);
 
180
    timeOutTimer.stop();
 
181
    kdDebug() << "connected\n" << endl;
 
182
}
 
183
 
 
184
void SMTP::connectTimedOut(void)
 
185
{
 
186
    timeOutTimer.stop();
 
187
 
 
188
    if(sock) 
 
189
        sock->enableRead(false);
 
190
    kdDebug() << "socket connection timed out\n" << endl;
 
191
    socketClose(sock);
 
192
    emit error(CONNECTTIMEOUT);
 
193
}
 
194
 
 
195
void SMTP::interactTimedOut(void)
 
196
{
 
197
    interactTimer.stop();
 
198
 
 
199
    if(sock)
 
200
        sock->enableRead(false);
 
201
    kdDebug() << "time out waiting for server interaction" << endl;
 
202
    socketClose(sock);
 
203
    emit error(INTERACTTIMEOUT);
 
204
}
 
205
 
 
206
void SMTP::socketRead(KSocket *socket)
 
207
{
 
208
    int n, nl;
 
209
 
 
210
    kdDebug() << "socketRead() called...\n" << endl;
 
211
    interactTimer.stop();
 
212
 
 
213
    if(socket == 0L || socket->socket() < 0)
 
214
        return;
 
215
    n = read(socket->socket(), readBuffer, SMTP_READ_BUFFER_SIZE-1 );
 
216
    readBuffer[n] = '\0';
 
217
    lineBuffer += readBuffer;
 
218
    nl = lineBuffer.find('\n');
 
219
    if(nl == -1)
 
220
        return;
 
221
    lastLine = lineBuffer.left(nl);
 
222
    lineBuffer = lineBuffer.right(lineBuffer.length() - nl - 1);
 
223
    processLine(&lastLine);
 
224
    if(connected)
 
225
        interactTimer.start(timeOut, TRUE);
 
226
}
 
227
 
 
228
void SMTP::socketClose(KSocket *socket)
 
229
{
 
230
    timeOutTimer.stop();
 
231
    disconnect(sock, SIGNAL(readEvent(KSocket *)), this, SLOT(socketRead(KSocket *)));
 
232
    disconnect(sock, SIGNAL(closeEvent(KSocket *)), this, SLOT(socketClose(KSocket *)));
 
233
    socket->enableRead(false);
 
234
    kdDebug() << "connection terminated\n" << endl;
 
235
    connected = false;
 
236
    if(socket){
 
237
        delete socket;
 
238
        socket = 0L;
 
239
        sock = 0L;
 
240
    }
 
241
    emit connectionClosed();
 
242
}
 
243
 
 
244
void SMTP::processLine(QString *line)
 
245
{
 
246
    int i, stat;
 
247
    QString tmpstr;
 
248
    
 
249
    i = line->find(' ');
 
250
    tmpstr = line->left(i);
 
251
    if(i > 3)
 
252
        kdDebug() << "warning: SMTP status code longer then 3 digits: " << tmpstr << "\n" << endl;
 
253
    stat = tmpstr.toInt();
 
254
    serverState = (SMTPServerStatus)stat;
 
255
    lastState = state;
 
256
 
 
257
    kdDebug() << "smtp state: [" << stat << "][" << *line << "]\n" << endl;
 
258
 
 
259
    switch(stat){
 
260
    case GREET:     //220
 
261
        state = IN;
 
262
        writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
 
263
        write(sock->socket(), writeString.ascii(), writeString.length());
 
264
        break;
 
265
    case GOODBYE:   //221
 
266
        state = QUIT;
 
267
        break;
 
268
    case SUCCESSFUL://250
 
269
        switch(state){
 
270
        case IN:
 
271
            state = READY;
 
272
            writeString = QString::fromLatin1("mail from: %1\r\n").arg(senderAddress);
 
273
            write(sock->socket(), writeString.ascii(), writeString.length());
 
274
            break;
 
275
        case READY:
 
276
            state = SENTFROM;
 
277
            writeString = QString::fromLatin1("rcpt to: %1\r\n").arg(recipientAddress);
 
278
            write(sock->socket(), writeString.ascii(), writeString.length());
 
279
            break;
 
280
        case SENTFROM:
 
281
            state = SENTTO;
 
282
            writeString = QString::fromLatin1("data\r\n");
 
283
            write(sock->socket(), writeString.ascii(), writeString.length());
 
284
            break;
 
285
        case DATA:
 
286
            state = FINISHED;
 
287
            finished = true;
 
288
            sock->enableRead(false);
 
289
            emit messageSent();
 
290
            break;
 
291
        default:
 
292
            state = CERROR;
 
293
            kdDebug() << "smtp error (state error): [" << lastState << "]:[" << stat << "][" << *line << "]\n" << endl;
 
294
            socketClose(sock);
 
295
            emit error(COMMAND);
 
296
            break;
 
297
        }
 
298
        break;
 
299
    case READYDATA: //354
 
300
        state = DATA;
 
301
        //        writeString = QString::fromLatin1("Subject: %1\n%2\n.\n").arg(messageSubject).arg(messageBody);
 
302
        writeString = QString::fromLatin1("Subject: %1\r\n").arg(messageSubject);
 
303
        writeString += QString::fromLatin1("From: %1\r\n").arg(senderAddress);
 
304
        kdDebug() << senderReplyTo << endl;
 
305
        if( (senderReplyTo != NULL) && senderReplyTo.contains("@") )
 
306
          {
 
307
            writeString += QString::fromLatin1("Reply-To: %1\r\n").arg(senderReplyTo);
 
308
          }
 
309
        writeString += QString::fromLatin1("To: %1\r\n\r\n").arg(recipientAddress);
 
310
        writeString += messageBody;
 
311
        writeString += QString::fromLatin1(".\r\n");
 
312
        write(sock->socket(), writeString.ascii(), writeString.length());
 
313
        break;
 
314
    case ERROR:     //501
 
315
        state = CERROR;
 
316
        kdDebug() << "smtp error (command error): [" << lastState << "]:[" << stat << "][" << *line << "]\n" << endl;
 
317
        socketClose(sock);
 
318
        emit error(COMMAND);
 
319
        break;
 
320
    case UNKNOWN:   //550
 
321
        state = CERROR;
 
322
        kdDebug() << "smtp error (unknown user): [" << lastState << "]:[" << stat << "][" << *line << "]\n" << endl;
 
323
        socketClose(sock);
 
324
        emit error(UNKNOWNUSER);
 
325
        break;
 
326
    default:
 
327
        state = CERROR;
 
328
        kdDebug() << "unknown response: [" << lastState << "]:[" << stat << "][" << *line << "]\n" << endl;
 
329
        socketClose(sock);
 
330
        emit error(UNKNOWNRESPONSE);
 
331
    }
 
332
} // processLine
 
333
 
 
334
#include "smtp.moc"