1 #ifndef AVOIRDESPEW_SRC_CURL_HPP 2 #define AVOIRDESPEW_SRC_CURL_HPP 3 4 /****************************************************************************** 5 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/examples/mit_exchanges_performance.cpp 2014 2017-03-26 16:02:05Z jmmcg $ 6 ** 7 ** Copyright (c) 2017 by J.M.McGuiness, coder@hussar.me.uk 8 ** 9 ** This library is free software; you can redistribute it and/or 10 ** modify it under the terms of the GNU Lesser General Public 11 ** License as published by the Free Software Foundation; either 12 ** version 2.1 of the License, or (at your option) any later version. 13 ** 14 ** This library is distributed in the hope that it will be useful, 15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 ** Lesser General Public License for more details. 18 ** 19 ** You should have received a copy of the GNU Lesser General Public 20 ** License along with this library; if not, write to the Free Software 21 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24 #include <boost/noncopyable.hpp> 25 26 #include <list> 27 #include <sstream> 28 #include <string> 29 #include <vector> 30 31 #include <curl/curl.h> 32 33 namespace jmmcg { 34 35 /** 36 * <a href="https://curl.haxx.se/libcurl/c/libcurl-tutorial.html">Curl tutorial</a>. 37 */ 38 class curl : boost::noncopyable { 39 public: 40 using recipients_t=std::list<std::string>; 41 using failures_t=std::vector<std::tuple<std::string, std::string>>; 42 43 class email_recipients : boost::noncopyable { 44 public: 45 ~email_recipients() noexcept(true); 46 47 /** 48 Add two recipients, in this particular case they correspond to the To: and Cc: addressees in the header, but they could be any kind of recipient. 49 */ 50 void push_back(std::string const &addr) noexcept(true); 51 bool empty() const noexcept(true); 52 53 private: 54 friend class curl; 55 56 curl_slist * recipients_=nullptr; 57 recipients_t addrs_; 58 }; 59 60 /** 61 \param smtp_url The hostname:port to which the email should be sent. 62 */ 63 curl(std::string const &smtp_url, unsigned short port, std::string const &username, std::string const &password, bool enable_logging, bool enable_ssl_verification=false) noexcept(false); 64 ~curl() noexcept(true); 65 66 /** 67 Note that this option isn't strictly required, omitting it will result in libcurl sending the MAIL FROM command with empty sender data. All autoresponses should have an empty reverse-path, and should be directed to the address in the reverse-path which triggered them. Otherwise, they could cause an endless loop. See RFC 5321 Section 4.5.5 for more details. 68 */ 69 void from(std::string const &from) noexcept(true); 70 71 /** 72 We're using a callback function to specify the payload (the headers and body of the message). You could just use the CURLOPT_READDATA option to specify a FILE pointer to read from. 73 */ 74 failures_t send(std::string const &subject, std::string const &body, recipients_t const &recipients) noexcept(false); 75 76 friend std::ostream &operator<<(std::ostream &os, curl const &c) noexcept(false) { 77 os<<"SMTP server: '"<<c.smtp_url_<<"'" 78 ", logon username: '"<<c.username_<<"'" 79 ", from: '"<<c.from_<<"'."; 80 return os; 81 } 82 83 private: 84 using payload_message_t=std::vector<std::string>; 85 struct upload_status { 86 size_t lines_read=0; 87 }; 88 89 CURL * const handle_; 90 const std::string smtp_url_; 91 const std::string username_; 92 const std::string password_; 93 std::string from_; 94 upload_status upload_ctx_; 95 96 static payload_message_t payload_text_strs_; 97 98 /** 99 If your server doesn't have a valid certificate, then you can disable part of the Transport Layer Security protection by setting the CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST options to 0 (false). That is, in general, a bad idea. It is still better than sending your authentication details in plain text though. Instead, you should get the issuer certificate (or the host certificate if the certificate is self-signed) and add it to the set of certificates that are known tolibcurl using CURLOPT_CAINFO and/or CURLOPT_CAPATH. See docs/SSLCERTS for more information. 100 */ 101 void ignore_ssl_verification() noexcept(true); 102 103 /** 104 Since the traffic will be encrypted, it is very useful to turn on debug information within libcurl to see what is happening during the transfer. 105 */ 106 void set_logging() noexcept(true); 107 108 static std::string current_time_for_email() noexcept(false); 109 void create_message(std::string const &to, std::string const &subject, std::string const &body) const noexcept(false); 110 static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp); 111 }; 112 113 } 114 115 #endif