• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:SSL_connect(ssl))

SSL_connect(ssl)でGメールからメールを受信する方法

このQ&Aのポイント
  • GメールからPOP3S接続でメールを受け取る方法について紹介します。
  • 接続の部分に問題がある場合、アドバイスを求めています。
  • SSL_connect(ssl)を使用して、GメールのPOP3サーバーに接続し、メールを受信することができます。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.2

RETRコマンドで読み取り完了したら、そのメールを削除して、QUITコマンドで切断していますから1通しか読み込めないのは想定内の動作のハズですけど、そこらヘンはどうなんですかね? CSQMailBoxTreeView::GmailProcessData()の呼び出し方次第ではココも正常動作が期待できませんが…。 前回の回答でも指摘しましたが普通のPOP3で正しく動作するもの作ってからの方がいいと思われますが…。 その際、LAN内の別マシンにPOP3サーバを構築すればWireSharkなどでパケットの内容は確認できますし。 # GmailのPOP3って…bad commandで切断されるのね…… あと…MessageBox()でもろもろの通知を出すと「そこで処理が止まる」ので通信扱う場合だと問題が発生することもありますのでご注意を。 # 私ならTRACE()やその類使いますね。(Win32SDKなんでOutputDebugString()ですが…)

uyama33
質問者

補足

関連する残りの部分です。 POP3 では、メールは取り出せます。 新しく、POP3S で接続しようとしています。 ご指摘の部分を参考に、デバッグを続けます。 ありがとうございました。 // MailAsync(); corresponding to the message SM_GASYNC3. LRESULT CSQMailBoxTreeView::GmailMailAsync(WPARAM , LPARAM lParam) { int GmailnBytesRead; char buf1[256]; int nEvent = (int)WSAGETSELECTEVENT(lParam); int nError = (int)WSAGETSELECTERROR(lParam); sprintf_s(buf1,"hasm %d error\r\n",nError); if( nError ){ MessageBox(buf1,"Error", MB_OK); } switch(nEvent){ case FD_CONNECT: break; case FD_WRITE: break; case FD_READ: // Receive waiting data GmailnBytesRead = SSL_read( ssl, // socket gbufRecv, // buffer sizeof(gbufRecv)-1 // max len to read //はみだしそう -1 付けた ); // recv flags // Check recv() return code if (GmailnBytesRead == 0){ // Connection has been closed. int erv = SSL_get_error(ssl, GmailnBytesRead); if(erv <= 0){ MessageBox("Connection closed unexpectedly", "recv() error", MB_OK); } break; } if (GmailnBytesRead < 0){ int erv = SSL_get_error(ssl, GmailnBytesRead); if(erv <= 0){ wsprintf((LPSTR)gszTemp, (LPSTR)"recv() error: %d", GmailnBytesRead); MessageBox( gszTemp,"recv() error",MB_OK); gszTemp[0] = '\0'; } break; } // Null terminate the buffer gbufRecv[GmailnBytesRead] = '\0'; //はみだしそう // And pass it to be interpreted GmailProcessData(gbufRecv, GmailnBytesRead); break; case FD_CLOSE: break; } fRet = TRUE; return 0; } LPSTR CSQMailBoxTreeView::GmailDecodeError(int ErrorCode) { static char Message[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)Message, 1024, NULL); return Message; } void CSQMailBoxTreeView::GmailMailDL2(){ reached = download = 0; in_header = 1; ((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("メール受信中です、しばらくお待ちください。"); GmailMailDL(); ((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("終了。"); }

その他の回答 (1)

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.1

>メールヘッダーの受信後に、本文を取り出す前に接続が切れます。 POP3Sで接続して、RETRコマンドの発行まで出来ているんでしょう? であれば、接続の時のコードを掲示してもあまり意味が無いと思いますが。 # SSL接続の方法などについて意味があるかも知れませんけど、ログイン出来ているならSSL接続は出来ていることになりませんか? 実際のデータ受信処理の辺りがどうなっているのか? が問題かと思いますが……。 LISTコマンドやTOPコマンド、RETRコマンドは1行受信して終了ではなく、 "."のみの行を受信するまで続きますがそこらヘン正しく処理していますか? # "\r\n.\r\n"が正確なとこですかねぇ。 POP3Sが~ではなく通常のPOP3でちゃんと処理できるかどうかを先にやってはどうですか? 自由に使えるメールサーバがあれば、こういう時は楽…なんですけどね。 実行しているWindowsに一時的にメールサーバ構築する。なんてのもアリでしょう。 「Windows メールサーバ」辺りで検索すると情報も見つかるでしょう。 # 私はMercury辺りを使ったことがありますが。 # 今はLAN内のメールサーバ(Linux+Dovecot)があるので使っていませんけど。

uyama33
質問者

お礼

続きです。(一部重複)接続できていて不安定ですが一度だけメール本文も取得できました。 case STATE_LIST: sscanf(lpStr, "%s %ld %ld", gszTemp, &lCount, &lSize); _itoa(lSize, c_strSize,10); wsprintf(gszTemp, "RETR %d\r\n",download); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags gnAppState = STATE_RETR; break; case STATE_RETR: if((lpStr[0]=='.') && (strlen(lpStr)==2)){ pDoc->D_hi.DoIt(pDoc->Mailstrs); strcpy_s(c_strTo, pDoc->D_hi.GetTo()); strcpy_s(c_strSubject, pDoc->D_hi.GetSubject()); strcpy_s(c_strFrom, pDoc->D_hi.GetFrom()); strcpy_s(c_strAttach, ""); // strcpy(c_strSize, ""); strcpy_s(c_strPriority, "2"); strcpy_s(c_strRead, "1");//未読1 , 既読0 if(mailfilter == 1){ ret = pDoc->GetPrgbyAddr(c_strFrom); if(ret == 0){ strcpy_s(c_strState, "3");//1:受信箱 2:送信済み 3:迷惑メール 4:ゴミ箱 }else{ strcpy_s(c_strState, "1");//1:受信箱 2:送信済み 3:迷惑メール 4:ゴミ箱 } }else{ strcpy_s(c_strState, "1");//1:受信箱 2:送信済み 3:迷惑メール 4:ゴミ箱 } strcpy_s(c_strDate, pDoc->D_hi.GetDate()); if(CFile::GetStatus("test2.bin", fs) == TRUE){CFile::Remove("test2.bin");} u_CStringArray2File("test2.bin", pDoc->Mailstrs); pDoc->AddNewMail("test2.bin"); pDoc->Mailstrs.RemoveAll(); // Send the QUIT command. And set the app state. if(0 == atoi(oc_Gmailradio)){ wsprintf(gszTemp, "DELE %d\r\n",download); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags } wsprintf(gszTemp, "QUIT\r\n"); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags gnAppState = STATE_QUIT; } else{// by uyama sbuf = lpStr; sbuf += "\n"; pDoc->Mailstrs.Add(sbuf);//lpSt + "\n"; } break; case STATE_QUIT: SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); ERR_free_strings(); CloseSocket(sock); if((state == -STATE_LIST ) || (state == -STATE_RETR)){ }else{ pDoc->m_pTreeView->nImageID = 1; if(reached == download){ pDoc->m_pListView->ShowReceived(); } if(reached>download){ in_header = 1; pDoc->Mailstrs.RemoveAll(); ((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("メール受信中です、しばらくお待ちください。"); GmailMailDL(); ((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetWindowText("終了。"); } } } } void CSQMailBoxTreeView::GmailProcessData(LPSTR lpBuf, int nBytesRead) { static char szResponse[4096]; static int nLen = 0; char *cp; // Is there enough room in our buffer for the new data? if ((nLen + nBytesRead) > sizeof(szResponse)){ MessageBox("Buffer overrun, data truncated","Error",MB_OK); nLen = 0; szResponse[0] = '\0'; return; } // Append the new data to our buffer strcat_s(szResponse, sizeof(szResponse), lpBuf); nLen = strlen(szResponse); // Process all full lines while(1){ // Does the buffer contain a full line? cp = strchr(szResponse, '\n'); if (cp == NULL) break; // We have a CR/LF pair // Replace the LF with a NULL *cp = '\0'; // And pass it to the ProcesLine() function GmailProcessLine( szResponse); // Move the remaining data to the front // of the buffer cp++; if (strlen(cp)) memmove(szResponse, cp, strlen(cp)+1); else szResponse[0] = '\0'; } }

uyama33
質問者

補足

void CSQMailBoxTreeView::GmailProcessLine(LPSTR lpStr) { int nRet, ret; long lCount; long lSize; CFileStatus fs; CString sbuf; BStringBuffer s(""); CSQMailBoxDoc* pDoc = GetDocument(); if(strlen(lpStr)==1 && in_header){ pDoc->GetHeaderInfor(); in_header = 0; } // Check response for error if ((lpStr[0] == '-') && (lpStr[1] == 'E') && (lpStr[2] == 'R') && (lpStr[3] == 'R')) { // MessageBox("Negative response: ","Error",MB_OK); switch(gnAppState) { case STATE_CONNECTING: MessageBox("Connection denied","Error",MB_OK); break; case STATE_USER: MessageBox("Unknown UserID\r\n","Error",MB_OK); break; case STATE_PASS: MessageBox("Wrong Password","Error",MB_OK); break; case STATE_STAT: MessageBox("STAT command not supported","Error",MB_OK); break; case STATE_LIST: state = -STATE_LIST; MessageBox("メールはありません。"); break; case STATE_RETR: state = -STATE_RETR; MessageBox("Negative RETR response."); break; case STATE_QUIT: MessageBox("QUIT command not supported","Error",MB_OK); break; } wsprintf(gszTemp, "QUIT\r\n"); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags gnAppState = STATE_QUIT; SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); ERR_free_strings(); CloseSocket(sock); return; } // We have a positive response switch(gnAppState) { case STATE_CONNECTING: // Send the USER portion of the login request and set the app state wsprintf(gszTemp, "USER %s\r\n", gszGmailUserId); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags gnAppState = STATE_USER; break; case STATE_USER: // Send the PASSword portion of the login request and set the app state wsprintf(gszTemp, "PASS %s\r\n", gszGmailPassword); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags gnAppState = STATE_PASS; break; case STATE_PASS: // Send the STAT command request and set the app state wsprintf(gszTemp, "STAT\r\n"); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flagsgs gnAppState = STATE_STAT; break; case STATE_STAT: // Read the STAT response and print the results sscanf(lpStr, "%s %ld %ld", gszTemp, &lCount, &lSize); if(download == 0){reached = lCount;} download += 1; wsprintf(gszTemp, "LIST %d\r\n",download); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags gnAppState = STATE_LIST; break; case STATE_LIST: sscanf(lpStr, "%s %ld %ld", gszTemp, &lCount, &lSize); _itoa(lSize, c_strSize,10); wsprintf(gszTemp, "RETR %d\r\n",download); nRet = SSL_write(ssl, // socket gszTemp, // data buffer strlen(gszTemp) // length of data ); // send flags gnAppState = STATE_RETR; break;

関連するQ&A