C language code for sending emails in linux

Source: Internet
Author: User
Tags base64 encode get ip socket error tmp file
C language code for sending emails in linux-general Linux technology-Linux programming and kernel information. The following is a detailed description. Currently, many users automatically obtain the ip address instead of the fixed ip address.
Program, after each time he accesses the Internet, his ip address is automatically sent to the specified email.
The implementation is very simple (of course, the premise is that you have the corresponding permissions,: D), by calling system (),
Put the program path in/etc/rc. local to enable each call. Use ifconfig to obtain the ip address,
Write a temporary file, read the file content to the buffer, and send it as the email body to the specified email.
Taking the 163.com smtp server as an example, the current smtp servers are all added with the verification function (different servers
The verification method is different, sina verification is different, the specific verification method is not studied), the communication process is
Such:
[Root @ localhost root] # telnet smtp.163.com 25
Trying 202.108.44.170...
Connected to smtp.163.com.
Escape character is '^]'.
220 Coremail SMTP (Anti Spam) System (163com [20030606])
Ehlo smtp.163.com
250-1900001.170
250-PIPELINING
250-AUTH LOGIN PLAIN NTLM
250-AUTH = LOGIN PLAIN NTLM
250 8 BITMIME
Auth login
334 VXNlcm5hbWU6
Xxxxxx (base64 encoded user name)
334 UGFzc3dvcmQ6
Xxxxx (base64 encoded password)
235 Authentication successful
Mail from: gyfxlt8.go@163.com
250 OK
Rcpt to: gymiles@sohu.com
250 OK
Data
354 End data .
Test
.
250 OK: queued as IMA5dQQvoEEGyE4C. 1
Quit
221 Bye
Connection closed by foreign host.



Smtp server return value table
-----------------------------------------------
500 Incorrect email address
501 Incorrect Parameter format
502 commands cannot be implemented
503 SMTP verification is required for the server
504 command parameters cannot be implemented
421 service not ready, disable Transmission Channel
450 the email operation is not completed and the mailbox is unavailable (for example, the mailbox is busy)
550 the requested email operation is incomplete and the email address is unavailable (for example, the email address is not found or cannot be accessed)
451 discard required operations; errors occurred during handling
551 users are not local. Please try
452 the system storage is insufficient and the required operations are not performed
552 excessive storage allocation, required operations not performed
553 the mailbox name is unavailable and the required operation is not performed (for example, the mailbox format is incorrect)
432 requires a password Conversion
534 authentication mechanism is too simple
538 encryption is required for the authentication mechanism currently requested
454 temporary authentication failed
530 authentication required

220 Service ready
250 the required email operation is completed
251 the user is not local and will forward
354 start email input, . End
221 disable transmission channels
334 Server Response verification Base64 string
235 Verification Successful
---------------------------------------------------

The process is obvious. Let's talk about the base64 encoding method:
Three strings can be separated (with less encoding followed by '='). We know that each character is 8 characters long,
In this way, the three characters are 24-bit. base64 encoding separates the three characters (24-bit) and six-bit characters into four characters,
Then compare the ascii values of the four characters with the following table and extract the corresponding characters, which are the final characters After encoding.
For example, the three characters abc are encoded as follows:
0110 0001 0110 0010 01100011
Now six digits and six digits are reorganized:
011000 010110 001001 100011
The resulting characters are:
00011000 00010110 00001001 00100011
Ascii code values: 24 22 9 35
Compare the following table to get the encoded character: YWJj
The program logic is as follows:
1. A> 2
2. (a & 0x03) <4 | (B> 4)
3. (B & 0x0f) <4 | (c> 6)
4. c & 0x3f
Then, compare the obtained values with the following table to obtain the encoded characters. For details, see the code.
Base64 encoding conversion table (from RFC2045)
--------------------------------------------------
Table 1: The Base64 Alphabet

Value Encoding
0 A 17 R 34 I 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6G 23X40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 B 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63/
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32g 49 x
16 Q 33 h 50 y
---------------------------------------------------

This code passes the test under thizlinux7.0
/*--------------------------------------
Code by sink (gymiles@sohu.com)
------------------------------------*/

# Include // Include socket
# Include
# Include // Include fopen (), fread (). fwrite (), fclose ()
# Include // Include system ()
# Include // Include gethostbyname ()

# Define PORT 25 // smtp port
# Define SIZE 1024
// Define mail commands
# Define EHLO 0
# Define AUTH 1
# Define USER 2
# Define PASS 3
# Define MAIL 4
# Define RCPT 5
# Define DATA 6
# Define CONT 7
# Define QUIT 8

Void base64enc (const char *, char *);

Int main (int argc, char * argv [])
{
Int sockfd;
Struct sockaddr_in server_addr;
Struct hostent * server_ip;
Int numbytes = 0, I = 0;
Char username [512] = ""; // mail username
Char passwd [512] = ""; // mail passwd

// Buff store data by recv (),
// Ip [SIZE] store data by fread () from ip_files (use "ifconfig> tmp. ip", het ip_files)
Char buff [512] = "", tmp [4] = "", ip [SIZE] = "";
Int ret = 0; // function return
FILE * f_open, * f_write;
Char * msg [9] = {""};
Char * n_return [9] = {""}; // return number

Msg [EHLO] = "ehlo smtp.163.com \ n ";
Msg [AUTH] = "auth login \ n ";
Base64enc ("your name", username );
Strcat (username, "\ n ");
Msg [USER] = username;
Base64enc ("your passwd", passwd );
Strcat (passwd, "\ n ");
Msg [PASS] = passwd;
Msg [MAIL] = "mail from: xxxxx@163.com \ n ";
Msg [RCPT] = "rcpt to: xxxxx@sohu.com \ n ";
Msg [DATA] = "data \ n ";
Msg [QUIT] = "quit \ n ";

N_return [EHLO] = "250 ";
N_return [AUTH] = "334 ";
N_return [USER] = "334 ";
N_return [PASS] = "235 ";
N_return [MAIL] = "250 ";
N_return [RCPT] = "250 ";
N_return [DATA] = "354 ";
N_return [CONT] = "250 ";



/*---------------------------
Copy self to/bin/getip
---------------------------*/
If (strcmp (argv [0], "/bin/getip ")! = 0) // if file/bin/getip is not existed, copy to it
{
If (f_open = fopen (argv [0], "rb") = NULL) // open self
{
Perror ("fopen argv [0] error ");
Return (-1 );
}

If (f_write = fopen ("/bin/getip", "wb") = NULL) // open the file which we will write
{
Perror ("fopen/bin/getip error ");
Return (-1 );
}
While (fread (tmp, sizeof (tmp), 1, f_open )! = 0) // read from currect file
{
If (fwrite (tmp, sizeof (tmp), 1, f_write) = 0) // write to/bin/getip
{
Perror ("fwrite error ");
Return (-1 );
}
}

Fclose (f_open); // close all files we have opened
Fclose (f_write );

// Chmod 755/bin/getip
If (ret = system ("chmod 755/bin/getip") =-1)
{
Perror ("system error ");
Return (-1 );
}

// Call system ("echo/bin/getip>/etc/rc. local ")
If (ret = system ("echo '/bin/getip &'>/etc/rc. local") =-1)
{
Perror ("system error ");
Return (-1 );
}
}

/*---------------------------
Get ip, use system () call ifconfig> tmp. ip
---------------------------*/
If (ret = system ("ifconfig>/tmp. ip") =-1)
{
Perror ("system error ");
Return (-1 );
}

/*-----------------------------
Read from tmp. ip, add it to msg [CONT]
-----------------------------*/
If (f_open = fopen ("/tmp. ip", "r") = NULL) // open/tmp. ip
{
Perror ("fopen error ");
Return (-1 );
}


I = 0;
While (fread (& ip , 1, 1, f_open ))! =-1) // read from tmp. ip
{
I ++;
If (I> SIZE) // if file is large than SIZE, only read SIZE bytes
Break;
}
Strncat (ip, "\ n. \ n", 3); // cat "\ n. \ n" to data
Msg [CONT] = ip;
Fclose (f_open );


/*-----------------------------
Rm tmp file
------------------------------*/
If (ret = system ("rm-rf/tmp. ip") =-1)
{
Perror ("system error ");
Return (-1 );
}


/*------------------------------
Connect server, and send command
------------------------------*/
// Because the host connect to internet by dail,
// So, it is possiabe that host have not connected when it start
// Then we sleep 5 miniutes, and try again until the host connect to internet
// We know the connection status by gethostbyname (), but this way is not always correct
While (server_ip = gethostbyname ("smtp.163.com") = NULL)
{
Herror ("gethostbyname error ");
Sleep (300 );
}
// Create a socket
If (sockfd = socket (AF_INET, SOCK_STREAM, 0) =-1)
{
Perror ("socket error ");
Return (-1 );
}
// Address information
Server_addr.sin_family = AF_INET; // host byte order
Server_addr.sin_port = htons (PORT); // short, network byte order
Server_addr.sin_addr = * (struct in_addr *) server_ip-> h_addr); // server ip
Bzero (& (server_addr.sin_zero), 8); // zero the rest of struct
// Connect server
If (connect (sockfd, (struct sockaddr *) & server_addr, sizeof (struct sockaddr) =-1)
{
Perror ("connect error ");
Return (-1 );
}
// If connect success, server return "220"
If (numbytes = recv (sockfd, buff, SIZE, 0) =-1)
{
Perror ("recv error ");
Return (-1 );
}
// Clean tmp
For (I = 0; I <4; I ++)
Tmp= '\ 0 ';
Strncpy (tmp, buff, 3 );
If (strcmp (tmp, "220 ")! = 0)
Return (-1 );

// Send msgs. if any step has a mistake, the "while" will be breaked, then send "quit" to end connection
I = EHLO;
While (I {
If (numbytes = send (sockfd, msg, Strlen (msg), 0) =-1)
{
Perror ("send error ");
Break;
}
// Sleep (1); we dont have to use it, because recv () can choke itself until it got Ed data
If (numbytes = recv (sockfd, buff, SIZE, 0) =-1)
{
Perror ("recv error ");
Break;
}
Strncpy (tmp, buff, 3 );

// Printf ("command: % s \ n", msg);
// Printf ("return buff: % s \ n", buff );
// Printf ("shocould return: % s \ n", n_return);

If (strcmp (tmp, n_return) = 0)
I ++;
Else
Break;

}


// Send quit to end mail connection
If (numbytes = send (sockfd, msg [QUIT], strlen (msg [QUIT]), 0) =-1)
{
Perror ("send error ");
Return (-1 );
}


Close (sockfd );
Return (0 );
}

/*-------------------------
Base64 encode function
-------------------------*/
Void base64enc (const char * instr, char * outstr)
{
Char * table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + /";
Int ipv_len = 0, I = 0, j = 0, pad = 0;
Unsigned char buf1 [4] = "", buf2 [4] = "";

Performance_len = strlen (instr );
Pad = pai_len % 3;
For (I = 0; I {
If (I = instr_len-pad)
Strncpy (buf1, & instr, Pad );
Else
Strncpy (buf1, & instr, 3 );

Buf2 [0] = buf1 [0]> 2;
Buf2 [1] = (buf1 [0] & 0x03) <4 | buf1 [1]> 4;
Buf2 [2] = (buf1 [1] & 0x0f) <2 | buf1 [2]> 6;
Buf2 [3] = buf1 [2] & 0x3f;
For (j = 0; j <4; j ++)
Buf2 [j] = table [buf2 [j];

If (I = instr_len-pad)
For (j = 3; j> pad; j --)
Buf2 [j] = ';

Strncat (outstr, buf2, 4 );
}

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.