--- build.xml 2008/07/07 16:38:13
+++ build.xml 2008/07/28 14:57:22
@@ -145,7 +145,7 @@
-Dwith-logchar=[utf-8|wchar_t|unichar] (default=utf-8 on Unix, wchar_t on Windows)
-Dwith-apr=APRPATH
-Dwith-apr-util=PATH
--Dwith-SMTP=[libesmtp, no] (default no)
+-Dwith-SMTP=[libesmtp, CDO, no] (default no)
-Dwith-ODBC=[unixODBC, iODBC, Microsoft, no] (default no)
@@ -165,6 +165,9 @@
+
+
+
@@ -334,7 +337,18 @@
-
+
+
+
+
+
+
+
+
--- configure.in 2008/07/07 16:38:13
+++ configure.in 2008/07/28 14:57:22
@@ -254,21 +254,29 @@
AC_MSG_CHECKING(for SMTP support)
AC_ARG_WITH(SMTP,
AC_HELP_STRING(--with-SMTP, [SMTP support. Accepted arguments :
- libesmtp, no (default=no)]),
+ libesmtp, CDO, no (default=no)]),
[ac_with_smtp=$withval],
[ac_with_smtp=no])
case "$ac_with_smtp" in
+ CDO)
+ AC_MSG_RESULT(CDO)
+ AC_CHECK_HEADER(cdosys.h,, AC_MSG_ERROR(CDO not found !))
+ AC_SUBST(HAS_LIBESMTP, 0, SMTP support through libesmtp library.)
+ AC_SUBST(HAS_CDO, 1, SMTP support through CDO library.)
+ ;;
libesmtp)
AC_MSG_RESULT(libesmtp)
AC_CHECK_LIB([esmtp], [smtp_create_session],,
AC_MSG_ERROR(libesmtp library not found !),
-lesmtp)
AC_SUBST(HAS_LIBESMTP, 1, SMTP support through libesmtp library.)
+ AC_SUBST(HAS_CDO, 0, SMTP support through CDO library.)
LIBS="-lesmtp $LIBS"
;;
- no)
+ no)
AC_MSG_RESULT(no)
AC_SUBST(HAS_LIBESMTP, 0, SMTP support through libesmtp library.)
+ AC_SUBST(HAS_CDO, 0, SMTP support through CDO library.)
;;
*)
AC_MSG_RESULT(???)
--- src/main/cpp/smtpappender.cpp 2008/07/28 14:22:05
+++ src/main/cpp/smtpappender.cpp 2008/07/28 16:09:10
@@ -29,6 +29,11 @@
#include
+#if LOG4CXX_HAVE_CDO
+// we need to include windows.h _before_ apr_strings.h which disables
+// definitions from windows.h (see WIN32_LEAN_AND_MEAN and _WIN32_WINNT)
+#include
+#endif
#include
#include
@@ -43,6 +48,17 @@
#include
#endif
+#if LOG4CXX_HAVE_CDO
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#endif
+
+
namespace log4cxx {
namespace net {
//
@@ -274,7 +290,267 @@
};
#endif
-
+
+#if LOG4CXX_HAVE_CDO
+ namespace {
+ /**
+ * Class wrapping CDO for sending mail
+ */
+ class CDOSender {
+ public:
+ CDOSender(const LogString& smtpHost,
+ int smtpPort,
+ const LogString& smtpUsername,
+ const LogString& smtpPassword,
+ Pool& p);
+ ~CDOSender();
+
+ void sendMail(const LogString& from,
+ const LogString& to,
+ const LogString& cc,
+ const LogString& bcc,
+ const LogString& subject,
+ const LogString& msg,
+ bool sendHtmlFormat,
+ Pool& p);
+
+ private:
+ /**
+ Check the result of a COM call. If it failed the function throws an
+ Exception.
+ */
+ void checkCoResult(HRESULT hr, const logchar* errorMsg);
+
+ CDO::IConfiguration* pConfig;
+ };
+
+ CDOSender::CDOSender(const LogString& smtpHost,
+ int smtpPort,
+ const LogString& smtpUsername,
+ const LogString& smtpPassword,
+ Pool& p)
+ : pConfig(0)
+ {
+ CDO::Fields* pFields = NULL;
+ CDO::Field* pField = NULL;
+ try
+ {
+ // create the SMTP configuration
+ HRESULT hr = ::CoCreateInstance(
+ CDO::CLSID_Configuration,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ CDO::IID_IConfiguration,
+ reinterpret_cast(&pConfig));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp configuration (1)"));
+
+ hr = pConfig->get_Fields(&pFields);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp configuration (2)"));
+
+ hr = pFields->get_Item(_variant_t(cdoSendUsingMethod), &pField);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp send method (1)"));
+ hr = pField->put_Value(_variant_t((long)CDO::cdoSendUsingPort));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp send method (2)"));
+ pField->Release();
+ pField = NULL;
+
+ hr = pFields->get_Item(_variant_t(cdoSMTPServer), &pField);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp server (1)"));
+ hr = pField->put_Value(_variant_t(smtpHost.c_str()));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp server (2)"));
+ pField->Release();
+ pField = NULL;
+
+ hr = pFields->get_Item(_variant_t(cdoSMTPServerPort), &pField);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp port (1)"));
+ hr = pField->put_Value(_variant_t((long)smtpPort));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp port (2)"));
+ pField->Release();
+ pField = NULL;
+
+ hr = pFields->get_Item(_variant_t(cdoSMTPAuthenticate), &pField);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp auth (1)"));
+
+ if (smtpUsername.empty() || smtpPassword.empty())
+ {// use anonymous SMTP
+ pField->put_Value(_variant_t((long)CDO::cdoAnonymous));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp auth (2)"));
+ pField->Release();
+ pField = NULL;
+ }
+ else
+ {// use basic SMTP authentication
+ pField->put_Value(_variant_t((long)CDO::cdoBasic));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp auth (3)"));
+ pField->Release();
+ pField = NULL;
+
+ hr = pFields->get_Item(_variant_t(cdoSendUserName), &pField);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp auth (4)"));
+ hr = pField->put_Value(_variant_t(_variant_t(smtpUsername.c_str())));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp auth (5)"));
+ pField->Release();
+ pField = NULL;
+
+ hr = pFields->get_Item(_variant_t(cdoSendPassword),& pField);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp auth (6)"));
+ hr = pField->put_Value(_variant_t(_variant_t(smtpPassword.c_str())));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup smtp auth (7)"));
+ pField->Release();
+ pField = NULL;
+ }
+
+ hr = pFields->Update();
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while updating smtp configuration (1)"));
+ pFields->Release();
+ pFields = NULL;
+
+ }
+ catch(_com_error& e)
+ {
+ try
+ {
+ if (pField)
+ pField->Release();
+ if (pFields)
+ pFields->Release();
+ }
+ catch(_com_error)
+ {}
+ catch(...)
+ {}
+
+ std::basic_ostringstream s;
+ s << LOG4CXX_STR("COM error occurred while seting up the SMTP configuration.")
+ << e.ErrorMessage();
+ throw Exception(s.str());
+ }
+ catch(...)
+ {
+ try
+ {
+ if (pField)
+ pField->Release();
+ if (pFields)
+ pFields->Release();
+ }
+ catch(_com_error)
+ {}
+ catch(...)
+ {}
+
+ LogString msg(LOG4CXX_STR("error occurred while seting up the SMTP configuration."));
+ throw Exception(msg);
+ }
+ }
+
+ CDOSender::~CDOSender()
+ {
+ if (pConfig)
+ pConfig->Release();
+ }
+
+ void CDOSender::sendMail(const LogString& from,
+ const LogString& to,
+ const LogString& cc,
+ const LogString& bcc,
+ const LogString& subject,
+ const LogString& msg,
+ bool sendHtmlFormat,
+ Pool& p)
+ {
+ CDO::IMessage* pMsg = NULL;
+ try
+ {
+ // create a message
+ HRESULT hr = ::CoCreateInstance(
+ CDO::CLSID_Message,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ CDO::IID_IMessage,
+ reinterpret_cast(&pMsg));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup mail (1)"));
+
+ // set message attributes
+ hr = pMsg->put_To(_bstr_t(to.c_str()));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup mail header TO"));
+
+ if (!cc.empty())
+ {
+ hr = pMsg->put_CC(_bstr_t(cc.c_str()));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup mail header CC"));
+ }
+
+ if (!bcc.empty())
+ {
+ hr = pMsg->put_BCC(_bstr_t(bcc.c_str()));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup mail header BCC"));
+ }
+
+ hr = pMsg->put_From(_bstr_t(from.c_str()));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup mail header From"));
+
+ hr = pMsg->put_Subject(_bstr_t(subject.c_str()));
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while setup mail header Subject"));
+
+ // set the message body
+ if (sendHtmlFormat)
+ {
+ pMsg->put_HTMLBody(_bstr_t(msg.c_str()));
+ }
+ else
+ {
+ pMsg->put_TextBody(_bstr_t(msg.c_str()));
+ }
+
+ // set the SMTP prperties
+ hr = pMsg->putref_Configuration(pConfig);
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while updating smtp configuration (2)"));
+
+ // send the mail
+ hr = pMsg->Send();
+ checkCoResult(hr, LOG4CXX_STR("Error occurred while sending the message"));
+ pMsg->Release();
+ pMsg = NULL;
+ }
+ catch(_com_error& e)
+ {
+ if (pMsg)
+ pMsg->Release();
+
+ std::basic_ostringstream s;
+ s << LOG4CXX_STR("COM error occurred while sending mail.")
+ << e.ErrorMessage();
+ LogString msg(LOG4CXX_STR("COM error occurred while sending mail."));
+ // LogLog::error(s.str());
+ throw Exception(msg);
+ }
+ catch(...)
+ {
+ if (pMsg)
+ pMsg->Release();
+
+ LogString msg(LOG4CXX_STR("error occurred while sending mail."));
+ // LogLog::error(s.str());
+ throw Exception(msg);
+ }
+ }
+
+ void CDOSender::checkCoResult(HRESULT hr, const logchar* errorMsg)
+ {
+ if (FAILED(hr))
+ {
+ std::basic_ostringstream s;
+ s << errorMsg << LOG4CXX_STR(" [HRESULT: ") << hr << LOG4CXX_STR("]");
+ // LogLog::error(s.str());
+
+ throw Exception(s.str());
+ }
+ }
+
+ } // anonymous namespace
+#endif // LOG4CXX_HAVE_CDO
+
class LOG4CXX_EXPORT DefaultEvaluator :
public virtual spi::TriggeringEventEvaluator,
public virtual helpers::ObjectImpl
@@ -327,10 +603,20 @@
: smtpPort(25), bufferSize(512), locationInfo(false), cb(bufferSize),
evaluator(evaluator)
{
+#if LOG4CXX_HAVE_CDO
+ HRESULT hr = ::CoInitialize(NULL);
+ if (hr == RPC_E_CHANGED_MODE)
+ {
+ throw Exception("Failed to initialize the COM library");
+ }
+#endif
}
SMTPAppender::~SMTPAppender()
{
+#if LOG4CXX_HAVE_CDO
+ ::CoUninitialize();
+#endif
finalize();
}
@@ -496,7 +782,7 @@
activate &= asciiCheck(bcc, LOG4CXX_STR("bcc"));
activate &= asciiCheck(from, LOG4CXX_STR("from"));
-#if !LOG4CXX_HAVE_LIBESMTP
+#if !LOG4CXX_HAVE_SMTP
errorHandler->error(LOG4CXX_STR("log4cxx built without SMTP support."));
activate = false;
#endif
@@ -537,7 +823,7 @@
value false is returned. */
bool SMTPAppender::checkEntryConditions()
{
-#if LOG4CXX_HAVE_LIBESMTP
+#if LOG4CXX_HAVE_SMTP
if((to.empty() && cc.empty() && bcc.empty()) || from.empty() || smtpHost.empty())
{
errorHandler->error(LOG4CXX_STR("Message not configured."));
@@ -598,7 +884,7 @@
*/
void SMTPAppender::sendBuffer(Pool& p)
{
-#if LOG4CXX_HAVE_LIBESMTP
+#if LOG4CXX_HAVE_SMTP
// Note: this code already owns the monitor for this
// appender. This frees us from needing to synchronize on 'cb'.
try
@@ -615,13 +901,31 @@
layout->appendFooter(sbuf, p);
+#if LOG4CXX_HAVE_LIBESMTP
SMTPSession session(smtpHost, smtpPort, smtpUsername, smtpPassword, p);
SMTPMessage message(session, from, to, cc,
bcc, subject, sbuf, p);
session.send(p);
+#endif
+#if LOG4CXX_HAVE_CDO
+ CDOSender sender(smtpHost,
+ smtpPort,
+ smtpUsername,
+ smtpPassword,
+ p);
+ bool sendHtmlFormat = layout->getContentType() == LOG4CXX_STR("text/html");
+ sender.sendMail(from,
+ to,
+ cc,
+ bcc,
+ subject,
+ sbuf,
+ sendHtmlFormat,
+ p);
+#endif
}
catch(std::exception& e)
{
--- src/main/include/log4cxx/private/log4cxx_private.h.in 2008/07/07 16:38:13
+++ src/main/include/log4cxx/private/log4cxx_private.h.in 2008/07/28 14:57:22
@@ -47,6 +47,9 @@
#define LOG4CXX_CHARSET_EBCDIC @CHARSET_EBCDIC@
#define LOG4CXX_HAVE_LIBESMTP @HAS_LIBESMTP@
+#define LOG4CXX_HAVE_CDO @HAS_CDO@
+#define LOG4CXX_HAVE_SMTP (LOG4CXX_HAVE_LIBESMTP || LOG4CXX_HAVE_CDO)
+
#define LOG4CXX_HAVE_SYSLOG @HAS_SYSLOG@
#define LOG4CXX_WIN32_THREAD_FMTSPEC "0x%.8x"
--- src/main/include/log4cxx/private/log4cxx_private.hw 2008/07/07 16:38:13
+++ src/main/include/log4cxx/private/log4cxx_private.hw 2008/07/28 14:57:22
@@ -76,6 +76,9 @@
#define LOG4CXX_HAVE_LIBESMTP 0
+#define LOG4CXX_HAVE_CDO 0
+#define LOG4CXX_HAVE_SMTP (LOG4CXX_HAVE_LIBESMTP || LOG4CXX_HAVE_CDO)
+
#define LOG4CXX_HAVE_SYSLOG 0
#define LOG4CXX_WIN32_THREAD_FMTSPEC "0x%.8x"
--- src/site/apt/building/ant.apt 2008/07/07 16:38:13
+++ src/site/apt/building/ant.apt 2008/07/28 14:57:22
@@ -136,7 +136,7 @@
*-------------------+---------------------------------------------------------------------------------------------+
| -Dwith-charset | Exteral character encoding, choice of utf-8, iso-8859-1, usascii, ebcdic, auto (default). |
*-------------------+---------------------------------------------------------------------------------------------+
-| -Dwith-SMTP | SMTP implementation for SMTPAppender, choice of libesmtp, no (default). |
+| -Dwith-SMTP | SMTP implementation for SMTPAppender, choice of libesmtp, CDO, no (default). |
*-------------------+---------------------------------------------------------------------------------------------+
| -Dwith-ODBC | OBDC implementation for ODBCAppender, choice of unixODBC, iODBC, Microsoft, no (default). |
*-------------------+---------------------------------------------------------------------------------------------+
@@ -172,6 +172,8 @@
If -Dwith-SMTP=libesmtp is specified, the build will attempt to build
libesmtp from source, unfortunately libesmtp depends on poll.h and will not build.
+
+ If -Dwith-SMTP=CDO is specified, the SMTPAppender will be built using CDO.
APR 1.2.12 has a known issue that will prevent
compilation with Visual Studio 6 unless a later Platform SDK is installed.
--- src/site/apt/building/autotools.apt 2008/07/07 16:38:13
+++ src/site/apt/building/autotools.apt 2008/07/28 14:57:22
@@ -50,7 +50,7 @@
*-------------------+---------------------------------------------------------------------------------------------+
| --with-charset | Exteral character encoding, choice of utf-8, iso-8859-1, usascii, ebcdic, auto (default). |
*-------------------+---------------------------------------------------------------------------------------------+
-| --with-SMTP | SMTP implementation for SMTPAppender, choice of libesmtp, no (default). |
+| --with-SMTP | SMTP implementation for SMTPAppender, choice of libesmtp, CDO, no (default). |
*-------------------+---------------------------------------------------------------------------------------------+
| --with-ODBC | OBDC implementation for ODBCAppender, choice of unixODBC, iODBC, Microsoft, no (default). |
*-------------------+---------------------------------------------------------------------------------------------+