⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smtpappender.cpp

📁 log4cxx 0.10 unix下编译包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <log4cxx/net/smtpappender.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/stringtokenizer.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/synchronized.h>
#if !defined(LOG4CXX)
#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>



#include <apr_strings.h>
#include <vector>

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::net;
using namespace log4cxx::spi;

#if LOG4CXX_HAVE_LIBESMTP
#include <auth-client.h>
#include <libesmtp.h>
#endif

namespace log4cxx {
    namespace net {
        //
        //   The following two classes implement an C++ SMTP wrapper over libesmtp.
        //   The same signatures could be implemented over different SMTP implementations
        //   or libesmtp could be combined with libgmime to enable support for non-ASCII
        //   content.  

#if LOG4CXX_HAVE_LIBESMTP        
        /**
         *   SMTP Session.
         */
        class SMTPSession {
        public:
           /**
           *   Create new instance.
           */
            SMTPSession(const LogString& smtpHost,
                        int smtpPort,
                        const LogString& smtpUsername,
                        const LogString& smtpPassword,
                        Pool& p) : session(0), authctx(0), 
                        user(toAscii(smtpUsername, p)), 
                        pwd(toAscii(smtpPassword, p)) {
                auth_client_init();
                session = smtp_create_session();
                if (session == 0) {
                    throw Exception("Could not initialize session.");
                }
                std::string host(toAscii(smtpHost, p));
                host.append(1, ':');
                host.append(p.itoa(smtpPort));
                smtp_set_server(session, host.c_str());
   
                authctx = auth_create_context();
                auth_set_mechanism_flags(authctx, AUTH_PLUGIN_PLAIN, 0);
                auth_set_interact_cb(authctx, authinteract, (void*) this);
   
                if (*user || *pwd) {
                    smtp_auth_set_context(session, authctx);
                }
            }
            
            ~SMTPSession() {
                 smtp_destroy_session(session);
                 auth_destroy_context(authctx);
            }
            
            void send(Pool& p) {
                 int status = smtp_start_session(session);
                 if (!status) {
                     size_t bufSize = 128;
                     char* buf = p.pstralloc(bufSize);
                     smtp_strerror(smtp_errno(), buf, bufSize);
                     throw Exception(buf);
                 }
            }
            
            operator smtp_session_t() {
                return session;
            }

            static char* toAscii(const LogString& str, Pool& p) {
                char* buf = p.pstralloc(str.length() + 1);
                char* current = buf;
                for(LogString::const_iterator iter = str.begin();
                    iter != str.end();
                    iter++) {
                    unsigned int c = *iter;
                    if (c > 0x7F) {
                       c = '?';
                    }
                    *current++ = c;
                }
                *current = 0;
                return buf;
            }
                        
            private:
            SMTPSession(SMTPSession&);
            SMTPSession& operator=(SMTPSession&);
            smtp_session_t session;
            auth_context_t authctx;
            char* user;
            char* pwd;

            /**
             *   This method is called if the SMTP server requests authentication.
             */
            static int authinteract(auth_client_request_t request, char **result, int fields,
              void *arg) {
              SMTPSession* pThis = (SMTPSession*) arg;
              for (int i = 0; i < fields; i++) {
                int flag = request[i].flags & 0x07;
                if (flag == AUTH_USER) {
                   result[i] = pThis->user;
                } else if(flag == AUTH_PASS) {
                   result[i] = pThis->pwd;
                }
              }
              return 1;
            }
            

        };
        
        /**
         *  A message in an SMTP session.
         */
        class SMTPMessage {
        public:
            SMTPMessage(SMTPSession& session, 
                        const LogString& from, 
                        const LogString& to,
                        const LogString& cc,
                        const LogString& bcc,
                        const LogString& subject,
                        const LogString msg, Pool& p) {
                 message = smtp_add_message(session);
                 body = current = toMessage(msg, p);
                 smtp_set_reverse_path(message, toAscii(from, p));
                 addRecipients(to, "To", p);
                 addRecipients(cc, "Cc", p);
                 addRecipients(bcc, "Bcc", p);
                 if (!subject.empty()) {
                    smtp_set_header(message, "Subject", toAscii(subject, p));
                 }
                 smtp_set_messagecb(message, messagecb, this); 
            }
            ~SMTPMessage() {
            }
            
        private:
           SMTPMessage(const SMTPMessage&);
           SMTPMessage& operator=(const SMTPMessage&);
           smtp_message_t message;
           const char* body;
           const char* current;
           void addRecipients(const LogString& addresses, const char* field, Pool& p) {
              if (!addresses.empty()) {
                char* str = p.pstrdup(toAscii(addresses, p));;
                smtp_set_header(message, field, NULL, str);
                char* last;
                for(char* next = apr_strtok(str, ",", &last);
                    next;
                    next = apr_strtok(NULL, ",", &last)) {
                    smtp_add_recipient(message, next);
                }
              }
          }
           static const char* toAscii(const LogString& str, Pool& p) {
               return SMTPSession::toAscii(str, p);
           }
           
           /**
            *   Message bodies can only contain US-ASCII characters and 
            *   CR and LFs can only occur together.
            */
           static const char* toMessage(const LogString& str, Pool& p) {
               //
               //    count the number of carriage returns and line feeds
               //
               int feedCount = 0;
               for(size_t pos = str.find_first_of(LOG4CXX_STR("\n\r"));
                   pos != LogString::npos;
                   pos = str.find_first_of(LOG4CXX_STR("\n\r"), ++pos)) {
                   feedCount++;
               }
               //
               //   allocate sufficient space for the modified message
               char* retval = p.pstralloc(str.length() + feedCount + 1);
               char* current = retval;
               char* startOfLine = current;
               //
               //    iterator through message
               //
               for(LogString::const_iterator iter = str.begin();
                   iter != str.end();
                   iter++) {
                   unsigned int c = *iter;
                   //
                   //   replace non-ASCII characters with '?'
                   //
                   if (c > 0x7F) {
                      *current++ = 0x3F; // '?'
                   } else if (c == 0x0A || c == 0x0D) {
                      //
                      //   replace any stray CR or LF with CRLF
                      //      reset start of line
                      *current++ = 0x0D;
                      *current++ = 0x0A;
                      startOfLine = current;
                      LogString::const_iterator next = iter + 1;
                      if (next != str.end() && (*next == 0x0A || *next == 0x0D)) {
                         iter++;
                      }
                   } else {
                      //
                      //    truncate any lines to 1000 characters (including CRLF)
                      //       as required by RFC.
                      if (current < startOfLine + 998) {
                        *current++ = (char) c;
                      }
                   }
               }
               *current = 0;
               return retval;
           }
           
           /**
            *  Callback for message.
            */
           static const char* messagecb(void** ctx, int* len, void* arg) {
               *ctx = 0;
               const char* retval = 0;
               SMTPMessage* pThis = (SMTPMessage*) arg;
               //   rewind message
               if (len == NULL) {
                   pThis->current = pThis->body;
               } else {
                  if (pThis->current) {
                    *len = strlen(pThis->current);
                  }
                  retval = pThis->current;
                  pThis->current = 0;
               }
               return retval;
           }
           
        };
#endif        
        
                class LOG4CXX_EXPORT DefaultEvaluator :
                        public virtual spi::TriggeringEventEvaluator,
                        public virtual helpers::ObjectImpl
                {
                public:
                        DECLARE_LOG4CXX_OBJECT(DefaultEvaluator)
                        BEGIN_LOG4CXX_CAST_MAP()
                                LOG4CXX_CAST_ENTRY(DefaultEvaluator)
                                LOG4CXX_CAST_ENTRY(spi::TriggeringEventEvaluator)
                        END_LOG4CXX_CAST_MAP()

                        DefaultEvaluator();

                        /**
                        Is this <code>event</code> the e-mail triggering event?
                        <p>This method returns <code>true</code>, if the event level
                        has ERROR level or higher. Otherwise it returns
                        <code>false</code>.
                        */
                        virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event);
                private:
                         DefaultEvaluator(const DefaultEvaluator&);
                         DefaultEvaluator& operator=(const DefaultEvaluator&);
                }; // class DefaultEvaluator
        
    }
}

IMPLEMENT_LOG4CXX_OBJECT(DefaultEvaluator)
IMPLEMENT_LOG4CXX_OBJECT(SMTPAppender)

DefaultEvaluator::DefaultEvaluator() {
}

bool DefaultEvaluator::isTriggeringEvent(const spi::LoggingEventPtr& event)
{
   return event->getLevel()->isGreaterOrEqual(Level::getError());
}

SMTPAppender::SMTPAppender()
: smtpPort(25), bufferSize(512), locationInfo(false), cb(bufferSize),
evaluator(new DefaultEvaluator())
{
}

/**
Use <code>evaluator</code> passed as parameter as the
TriggeringEventEvaluator for this SMTPAppender.  */
SMTPAppender::SMTPAppender(spi::TriggeringEventEvaluatorPtr evaluator)
: smtpPort(25), bufferSize(512), locationInfo(false), cb(bufferSize),
evaluator(evaluator)
{
}

SMTPAppender::~SMTPAppender()
{
   finalize();
}

bool SMTPAppender::requiresLayout() const { 
    return true; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -