📄 empop3c.c
字号:
/* * Embedded POP3 Client * * ./software/ch6/empop3c/empop3c.c * * mtj@cogitollc.com * */#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <unistd.h>#include <string.h>#include <stdio.h>#include "empop3c.h"#define POP3_PORT 110#define SUCCESS "+OK"#define FAILURE "-ERR"#define MAX_LINE 512static int sock=-1;static int retIndex;static char buffer[MAX_LINE+1];/* * dialog() * * Perform a dialog transaction with the connected server. In this * dialog, a command may be sent but a response is always returned. * * The user must pass in a character buffer containing an optional * command (null string if no command is to be sent) and then the * same string is used to collect the response. * * The function returns 0 on success, -1 on error. * */static int dialog( int sock, char *command ){ int ret, len; if ( strlen(command) > 0 ) { len = strlen( command ); if (write( sock, command, len ) != len) return -1; } ret = read( sock, command, MAX_LINE ); if ( ret > 0 ) command[ret] = 0; else return -1; if (strncmp( command, "+OK", 3 )) return -1; return 0;}/* * pop3cConnect() * * Connect to a POP3 server using the server, username and password passed * in to the function. * * The number of messages is returned on success, -1 on failure. * */int pop3cConnect ( char *pop3Server, char *user, char *pass ){ int result; struct sockaddr_in servaddr; sock = socket( AF_INET, SOCK_STREAM, 0 ); bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_port = htons( 110 ); servaddr.sin_addr.s_addr = inet_addr( pop3Server ); if ( servaddr.sin_addr.s_addr == 0xffffffff ) { struct hostent *hptr = (struct hostent *)gethostbyname( pop3Server ); if ( hptr == NULL ) { return -1; } else { struct in_addr **addrs; addrs = (struct in_addr **)hptr->h_addr_list; memcpy( &servaddr.sin_addr, *addrs, sizeof(struct in_addr) ); } } do { result = connect( sock, (struct sockaddr *)&servaddr, sizeof(servaddr) ); if ( result < 0 ) break; /* Look for the salutation */ buffer[0] = 0; result = dialog( sock, buffer ); if ( result < 0 ) break; result = -1; /* Send the USER login */ sprintf( buffer, "USER %s\n", user ); result = dialog( sock, buffer ); if ( result < 0 ) break; result = -1; /* Send the PASS login */ sprintf( buffer, "PASS %s\n", pass ); result = dialog( sock, buffer ); if ( result < 0 ) break; result = -1; /* Finally, get the number of emails waiting */ strcpy( buffer, "STAT\n" ); result = dialog( sock, buffer ); if ( result < 0 ) break; sscanf( buffer, "+OK %d", &result ); retIndex = 1; } while (0); if ( result < 0 ) { close( sock ); sock = -1; } return result;}/* * pop3cRetrieve() * * Retrieve a message from the pop3c connection. This function is state * driven and therefore, the first message is returned, and subsequent * calls will return subsequent messages. The user must perform a * pop3cDelete in order to grab the next message. * * The message size is returned on success, -1 on failure. * */int pop3cRetrieve ( mail_t *mail, int totalLen ){ int result, i, bufIdx=0, state, stop, len; /* Send the Retrieve command */ sprintf( buffer, "RETR %d\n", retIndex ); result = dialog( sock, buffer ); if ( result < 0 ) return -1; /* Skip the +OK response string and grab any data (end with CRLF) */ len = strlen( buffer ); for ( i = 0 ; i < len-1 ; i++ ) { if ( (buffer[i] == 0x0d) && (buffer[i+1] == 0x0a) ) { len -= i-2; memmove( mail->email, &buffer[i+2], len ); break; } } state = stop = 0; while (!stop) { if (bufIdx+len > totalLen - 80) break; /* Search for the end-of-mail indicator in the current buffer */ for ( i = bufIdx ; i < bufIdx+len ; i++ ) { if ( (state == 0) && (mail->email[i] == 0x0d) ) state = 1; else if ( (state == 1) && (mail->email[i] == 0x0a) ) state = 2; else if ( (state == 2) && (mail->email[i] == 0x0d) ) state = 1; else if ( (state == 2) && (mail->email[i] == '.') ) state = 3; else if ( (state == 3) && (mail->email[i] == 0x0d) ) state = 4; else if ( (state == 4) && (mail->email[i] == 0x0a) ) { stop = 1; break; } else state = 0; } bufIdx += (i-bufIdx); if (!stop) { len = read( sock, &mail->email[bufIdx], (totalLen-bufIdx) ); if ( (len <= 0) || (bufIdx+len > totalLen) ) { break; } } } bufIdx -= 3; mail->email[bufIdx] = 0; mail->email_len = bufIdx; return bufIdx;}/* * pop3cDelete() * * Delete a message from the pop3c connection. The message deleted is the * last retrieved from the POP3 server. This function also increments the * message index so that the next message may be retrieved. * * A 0 is returned on success, -1 on failure. * */int pop3cDelete ( void ){ int result; /* Send the USER login */ sprintf( buffer, "DELE %d\n", retIndex++ ); result = dialog( sock, buffer ); if ( result < 0 ) return -1; result = -1; return( result );}/* * pop3cDisconnect() * * Disconnect from the current POP3 connection. * * A 0 is returned on success, -1 on failure. * */int pop3cDisconnect ( void ){ int result; strcpy( buffer, "QUIT\n" ); result = dialog( sock, buffer ); if ( result < 0 ) return -1; return 0;}/* * Copyright (c) 2002 Charles River Media. All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, is hereby granted without fee provided * that the following conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * 3. Neither the name of Charles River Media nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY CHARLES RIVER MEDIA AND CONTRIBUTERS * 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CHARLES * RIVER MEDIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARAY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -