前章ではPOP3サーバに接続したら、すぐに接続を切ってしまいました。
今回は、ユーザー名やパスワードを入力して、サーバーにメールが来ているかどうかをチェックしてみます。
サーバーに接続後
USER USER名\r\nを送信します。成功すると
+OK xxxxxxと返事が来ます。 次に、
PASS パスワード\r\nを送信します。 成功すれば
+OK xxxxxxxと返事が来ます。
これで、ログインできました。 次にLISTコマンドを送ります。 サーバーにメールが来ていれば、
+OK n visible message(xxxx octets) 1 xxxxx 2 xxxxx 3 xxxxx .というような返事が来ます。 最後は「.\r\n」です。 これを受信するまでrecv関数を繰り返して呼び出さなくてはいけません。
では、プログラムを見てみましょう。(もちろん、プロジェクトにWsock32.libを参加させなくてはいけまくせん。)
// pop02.cpp
#include <stdio.h>
#include <winsock2.h>
int main()
{
    char szServer[64], szBuf[1024], szPort[8], szUser[64], szPass[64];
    u_int port;
    WSADATA wsaData;
    int nRtn;
    SOCKET s;
    SOCKADDR_IN saddr;
    HOSTENT *lpHost;
    unsigned int addr;
    printf("POP3サーバー---");
    gets(szServer);
    printf("ポート番号---");
    gets(szPort);
    if (strcmp(szPort, "") == 0)
        strcpy(szPort, "110");
    port = (u_int)atoi(szPort);
    printf("ポート番号を%dに設定しました\n", port);
    printf("ユーザー名---");
    gets(szUser);
    printf("パスワード---");
    gets(szPass);
    nRtn = WSAStartup(MAKEWORD(1, 1), &wsaData);
    if (nRtn != 0) {
        perror("WSAStartupp失敗です\n");
        return -1;
    }
    s = socket(PF_INET, SOCK_STREAM, 0);
    if (s == INVALID_SOCKET) {
        perror("ソケット作成失敗\n");
        WSACleanup();
        return -2;
    }
    lpHost = gethostbyname(szServer);
    if (lpHost == NULL) {
        addr = inet_addr(szServer);
        lpHost = gethostbyaddr((char *)&addr, 4, AF_INET);
        wsprintf(szBuf, "%sが見つかりません\n", szServer);
        perror(szBuf);
        return -3;
    }
    memset(&saddr, 0, sizeof(SOCKADDR_IN));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    saddr.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list);
    if (connect(s, (PSOCKADDR)&saddr, sizeof(saddr)) != 0) {
        perror("サーバーソケットに接続失敗\n");
        closesocket(s);
        WSACleanup();
        return -4;
    }
    memset(szBuf, '\0', sizeof(szBuf));
    recv(s, szBuf, (int)sizeof(szBuf) - 1, 0);
    printf(szBuf);
    if (strstr(szBuf, "+OK") != szBuf) {
        perror("サーバーは+OKを返しませんでした\n");
        closesocket(s);
        WSACleanup();
        return -5;
    }
    wsprintf(szBuf, "USER %s\r\n", szUser);
    send(s, szBuf, (int)strlen(szBuf), 0);
    
    memset(szBuf, '\0', sizeof(szBuf));
    recv(s, szBuf, (int)sizeof(szBuf) - 1, 0);
    printf(szBuf);
    if (strstr(szBuf, "+OK") != szBuf) {
        perror("ユーザー名が正しくありません\n");
        closesocket(s);
        WSACleanup();
        return -6;
    }
    wsprintf(szBuf, "PASS %s\r\n", szPass);
    send(s, szBuf, (int)strlen(szBuf), 0);
    memset(szBuf, '\0', sizeof(szBuf));
    recv(s, szBuf, (int)sizeof(szBuf) - 1, 0);
    printf(szBuf);
    if (strstr(szBuf, "+OK") != szBuf) {
        perror("パスワードが不正です\n");
        closesocket(s);
        WSACleanup();
        return -7;
    }
    wsprintf(szBuf, "%s\r\n", "LIST");
    send(s, szBuf, (int)strlen(szBuf), 0);
        
    while (1) {
        memset(szBuf, '\0', sizeof(szBuf));
        nRtn = recv(s, szBuf, (int)sizeof(szBuf) - 1, 0);
        printf(szBuf);
        if (nRtn == SOCKET_ERROR) {
            perror("エラーが発生しました\n");
            break;
        }
        if (strstr(szBuf, ".\r\n") != NULL)
            break;
    }
                
    strcpy(szBuf, "QUIT\r\n");
    send(s, szBuf, (int)strlen(szBuf), 0);
    memset(szBuf, '\0', sizeof(szBuf));
    recv(s, szBuf, (int)sizeof(szBuf) - 1, 0);
    printf(szBuf);
    closesocket(s);
    WSACleanup();
    return 0;
}
では、実行結果を見てみましょう。
左の例では、プロクシメールを利用しているため、ポート番号は110番以外を使用しています。
直接メールサーバに接続するには110番を使います。
Update Mar/22/2004 By Y.Kumei