network programming
linux
SMTP
protocol stack
請勿用於非法用途或塞垃圾, 詐騙, 等 郵件
Author: WhoAmI
e-mail: kccddb@gmail.com
Date: 20220726
Copyright: CC BY-NC-SA
請自行修改
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> /* struct hostent, gethostbyname */
/*
S: 220 www.example.com ESMTP Postfix
C: HELO mydomain.com
S: 250 Hello mydomain.com
C: MAIL FROM: <sender@mydomain.com>
S: 250 Ok
C: RCPT TO: <friend@example.com>
S: 250 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: Subject: test message
C: From:""< sender@mydomain.com>
C: To:""< friend@example.com>
C:
C: Hello,
C: This is a test.
C: Goodbye.
C: .
S: 250 Ok: queued as 12345
C: quit
S: 221 Bye
*/
typedef struct _tsmtp{
char *c;
char *data;
}Tsmtp;
const char mailbody[]=
"Subject: test message\r\n"
"From:""< sender@mydomain.com>\r\n"
"To:< kkkxyz@gmail.com>\r\n"
"\r\n"
"Hello,\r\n"
"This is a test.\r\n"
"Goodbye.\r\n"
"\r\n";
#define TOFCU 1
#ifdef TOFCU
Tsmtp smtp_c[]={{"HELO ","xyz.edu.tw\r\n"},\
{"MAIL FROM: ","kkxyz@xyz.edu.tw\r\n"},\
{"RCPT TO: ","kkxyz@xyz.edu.tw\r\n"},\
{"DATA","\r\n"},{mailbody,"\r\n.\r\n"},{"QUIT","\r\n"},NULL};
#else
Tsmtp smtp_c[]={{"HELO ","xyz.edu.tw\r\n"},\
{"MAIL FROM: ","xyz@xyz.edu.tw\r\n"},\
{"RCPT TO: ","kkkkxyz@gmail.com\r\n"},\
{"DATA","\r\n"},{mailbody,"\r\n.\r\n"},{"QUIT","\r\n"},NULL};
#endif
char smtp_from[256]="sender@mydomain.com";
void error(const char *msg) { perror(msg); exit(0); }
static int read_delay_ms(int fd,int msec)
{
struct timeval tval;
fd_set readfds;
int n;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
tval.tv_sec = 0;
tval.tv_usec = msec*1000;
n = select(fd+1, &readfds, NULL, NULL, &tval);
return n;
}
static int read_delay_s(int fd,int sec)
{
struct timeval tval;
fd_set readfds;
int n;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
tval.tv_sec = sec;
tval.tv_usec = 0;
n = select(fd+1, &readfds, NULL, NULL, &tval);
return n;
}
int main(int argc,char *argv[])
{
int i;
/* SMPT port=25 */
int portno= 25;
char *host ="mymail.fun.edu.tw"; /
struct hostent *server;
struct sockaddr_in serv_addr;
int sockfd, bytes, sent, received, total, message_size;
char response[4096];
int step;
char message[512];
int tt;
printf("Starting...%s\n",host);
/* create the socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
/* lookup the ip address */
server = gethostbyname(host);
if (server == NULL) error("ERROR");
/* fill in the structure */
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
/* connect the socket */
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
/* send the request */
step=0;
printf("Starting...%s:%d\n",host,portno);
for(step=0;step<8;step++){
/* receive the response */
printf("Step %d\n",step);
memset(response,0,sizeof(response));
total = sizeof(response)-1;
received = 0;
do {
if(step==5){
tt=read_delay_s(sockfd,15);
}else tt=read_delay_ms(sockfd,1000);
if(tt<=0)break;
bytes = read(sockfd,response+received,total-received);
if (bytes < 0)
error("ERROR reading response from socket");
if (bytes == 0)
break;
received+=bytes;
} while (received < total);
printf("Step %d: Recv %d bytes\n",step, received);
if (received == total)
error("ERROR storing complete response from socket");
response[received]=0;
printf("RECV form server:%s\n",response);
if(smtp_c[step].c!=NULL){
if(smtp_c[step].c[0]=='\0')goto END;
}else goto END;
sprintf(message,"%s%s",smtp_c[step].c,smtp_c[step].data);
total = strlen(message);
printf("SEND[%d]:%s\n",total,message);
sent = 0;
if(total>0){
do {
bytes = write(sockfd,message+sent,total-sent);
if (bytes < 0)
error("ERROR writing message to socket");
if (bytes == 0)
break;
sent+=bytes;
} while (sent < total);
printf("write %d bytes\n",sent);
}else break;
}//for loop
END:
/* close the socket */
close(sockfd);
/* process response */
printf("Response:\n%s\n",response);
return 0;
}
/*
$ ./smpt.exe smtp.xyz.edu.tw
Starting...mymail.xyz.edu.tw
Starting...mymail.xyz.edu.tw:25
Step 0
Step 0: Recv 99 bytes
RECV form server:220 Mymail ESMTP Service(Mail2000 ESMTP Server V6.00) ready Sat, 23 Feb 2019 14:16:24 +0800 (CST)
SEND[17]:HELO xyz.edu.tw
write 17 bytes
Step 1
Step 1: Recv 12 bytes
RECV form server:250 Mymail
SEND[29]:MAIL FROM: kkxyz@xyz.edu.tw
write 29 bytes
Step 2
Step 2: Recv 34 bytes
RECV form server:250 Sender <kkxyz@xyz.edu.tw> OK
SEND[27]:RCPT TO: kkxyz@xyz.edu.tw
write 27 bytes
Step 3
Step 3: Recv 37 bytes
RECV form server:250 Recipient <kkxyz@xyz.edu.tw> OK
SEND[6]:DATA
write 6 bytes
Step 4
Step 4: Recv 35 bytes
RECV form server:354 Enter mail, end <CRLF>.<CRLF>
SEND[123]:
Subject: test message
From:< sender@mydomain.com>
To:< kkkkxyz@gmail.com>
Hello,
This is a test.
Goodbye.
.
write 123 bytes
Step 5
Step 5: Recv 35 bytes
RECV form server:250 Message accepted for delivery
SEND[6]:QUIT
write 6 bytes
Step 6
Step 6: Recv 12 bytes
RECV form server:221 Mymail
Response:
221 Mymail
laikc@laikcpc ~
$
*/
Authors: CrazyDog, CrazyMonkeyemail: kccddb@gmail.comDate: 20230222
Mar 14, 2025Author: \mathcal{CrazyDog}, Ph.D. in Electrical Engineering, NCTUemail: kccddb@gmail.comDate: 20230910
Nov 4, 2024Author: WhoAmI Date: 20230523 email:kccddb@gmail.com Copyright: CC BY-NC-SA 《荀子‧勸學》不積跬步,無以至千里;不積小流,無以成江海。 I. Mutex variables MUST be declared with type pthread_mutex_t, and must be initialized before they can be used. II. 了解 pthread_mutex_lock / pthread_mutex_unlock 與可能問題和代價 III. 程式執行效率與startvation 等問題
Jul 11, 2024Author: WhoAmIemail: kccddb@gmail.com
Dec 6, 2023or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up