libcURL TLS SMTP执行无报错但无法正常发送邮件问题排查
Hey there, let's break down why your smtp-tls.c works on the first run but fails silently afterward—even though your logs look like the SMTP conversation completes successfully.
First, let's recap your provided run log (formatted for clarity):
* Rebuilt URL to: smtp://smtp.gmail.com:587/ * Trying +++.+++.+++.+++... * TCP_NODELAY set * Connected to smtp.gmail.com (173.194.76.108) port 587 (#0) < 220 smtp.gmail.com ESMTP o107sm45550896wrc.63 - gsmtp > EHLO ++++++++++ < 250-smtp.gmail.com at your service, [+++.+++.+++.+++] < 250-SIZE 35882577 < 250-8BITMIME < 250-STARTTLS < 250-ENHANCEDSTATUSCODES < 250-PIPELINING < 250-CHUNKING < 250 SMTPUTF8 > STARTTLS < 220 2.0.0 Ready to start TLS * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: ../cacert.pem CApath: none * SSL connection using TLSv1.2 / +++.+++.+++.+++ * Server certificate: * subject: C=US; ST=California; L=Mountain View; O=Google Inc; CN=smtp.gmail.com * start date: Dec 13 14:11:54 2017 GMT * expire date: Mar 7 13:03:00 2018 GMT * subjectAltName: host "smtp.gmail.com" matched cert's "smtp.gmail.com" * issuer: C=US; O=Google Trust Services; CN=Google Internet Authority G3 * SSL certificate verify ok. > EHLO ++++++++++ < 250-smtp.gmail.com at your service, [+++.+++.+++.+++] < 250-SIZE 35882577 < 250-8BITMIME < 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH < 250-ENHANCEDSTATUSCODES < 250-PIPELINING < 250-CHUNKING < 250 SMTPUTF8 > AUTH LOGIN < 334 VXNlcm5hbWU6 > YjN0M2xnZXVzZUBnbWFpbC5jb20= < 334 UGFzc3dvcmQ6 > VW5kM3J0NGtpbmc= < 235 2.7.0 Accepted > MAIL FROM:<++++++++++@+++++++++.+++> < 250 2.1.0 OK o107sm45550896wrc.63 - gsmtp > RCPT TO:<++++++++++@+++++++++.+++> < 250 2.1.5 OK o107sm45550896wrc.63 - gsmtp > RCPT TO:<++++++++++@+++++++++.+++> < 250 2.1.5 OK o107sm45550896wrc.63 - gsmtp > DATA < 354 Go ahead o107sm45550896wrc.63 - gsmtp < 250 2.0.0 OK 1516030190 o107sm45550896wrc.63 - gsmtp * Connection #0 to host smtp.gmail.com left intact
Key Observation from the Log
The SMTP flow is technically successful: Gmail returns 250 2.0.0 OK after you send the DATA command, which means it accepted the message for delivery. So the issue isn't in authentication, TLS setup, or message submission—it's happening after the server takes the message, or in how your code handles repeated runs.
Possible Causes & Fixes
1. Resource Leaks or Improper Cleanup in Your VC++ Code
Since it works once but fails afterward, your code might not be resetting libcurl resources correctly between runs:
- Clean up libcurl globally: After each send, call
curl_global_cleanup(), and reinitialize withcurl_global_init(CURL_GLOBAL_ALL)before the next send. - Reset or recreate CURL handles: If you're reusing a
CURL*handle, callcurl_easy_reset(handle)to clear all previous options before setting new ones. Alternatively, create a new handle each time (safer for repeated executions). - Check VC++ memory issues: Use Visual Studio's debugger memory profiler to look for dangling pointers or leaks that could cause silent failures on subsequent runs.
2. Gmail's Filtering or Spam Policies
Even if Gmail accepts the message, it might route it to spam or discard it silently:
- Check recipient spam folders: First, have recipients check their spam/junk folders—generic test messages from new senders often end up here.
- Use an App Password (if 2FA is enabled): If your Gmail account has two-factor authentication turned on, a regular password won't work for SMTP. Generate an App Password in your Google Account settings and use that instead.
- Verify domain authentication (if using a custom domain): If you're sending from a non-Gmail address, ensure your domain has valid SPF and DKIM records—Gmail is strict about these to prevent spoofing.
3. Malformed Message Content
Your log doesn't show the actual message body sent after the DATA command. If the message is missing required headers or isn't formatted correctly, Gmail might discard it even after accepting it:
- Follow RFC 5322 standards: Your message must include
From,To, andSubjectheaders, and end with a single.on a line by itself to signal the end of the DATA phase. Example valid message:From: "Your Name" <your-email@domain.com> To: "Recipient" <recipient@domain.com> Subject: Test Email This is the message body. . - Ensure the terminating
.is correct: If you miss this, or if it's not on a line by itself, Gmail might not process the message even though it returns a success code.
4. Gmail Rate Limiting
Gmail has strict rate limits for outgoing messages. If you're sending multiple messages in quick succession, Gmail might throttle you silently (even if it returns a success code):
- Add delays between sends: Try adding a 60-120 second delay between subsequent send attempts to avoid hitting rate limits.
- Check your account's sending limits: Regular Gmail accounts have a daily limit of around 500 messages—if you're sending more than that, you'll get throttled.
Quick Test to Isolate the Issue
Modify your code to log the entire message body sent after the DATA command. This will let you confirm if the message is formatted correctly. Also, try creating a brand new libcurl session for each send instead of reusing resources—this will rule out cleanup issues.
内容的提问来源于stack exchange,提问作者pope

