Sendmail implementation + filtered streams.

This commit is contained in:
Vincent Richard 2005-04-28 10:57:41 +00:00
parent 64561ac5af
commit 38a8632828
37 changed files with 1025 additions and 151 deletions

View File

@ -2,6 +2,19 @@
VERSION 0.7.1cvs VERSION 0.7.1cvs
================ ================
2005-04-27 Vincent Richard <vincent@vincent-richard.net>
* progressionListener.{hpp|cpp}: moved to 'vmime::utility' package since
this can be of general use.
* stream.{hpp|cpp}: added a bufferedStreamCopy() function which can
take a 'progressionListener' parameter.
* filteredStream.{hpp|cpp}: new feature added: filtered input and
output streams.
* Added 'sendmail' transport service for local delivery.
2005-04-19 Vincent Richard <vincent@vincent-richard.net> 2005-04-19 Vincent Richard <vincent@vincent-richard.net>
* defaultParameter.cpp: fixed a bug in implementation of RFC-2231 (values * defaultParameter.cpp: fixed a bug in implementation of RFC-2231 (values

View File

@ -148,8 +148,10 @@ libvmime_sources = [
'vmime.hpp', 'vmime.hpp',
'utility/file.hpp', 'utility/file.hpp',
'utility/datetimeUtils.cpp', 'utility/datetimeUtils.hpp', 'utility/datetimeUtils.cpp', 'utility/datetimeUtils.hpp',
'utility/filteredStream.cpp', 'utility/filteredStream.hpp',
'utility/md5.cpp', 'utility/md5.hpp', 'utility/md5.cpp', 'utility/md5.hpp',
'utility/path.cpp', 'utility/path.hpp', 'utility/path.cpp', 'utility/path.hpp',
'utility/progressionListener.hpp',
'utility/random.cpp', 'utility/random.hpp', 'utility/random.cpp', 'utility/random.hpp',
'utility/smartPtr.hpp', 'utility/smartPtr.hpp',
'utility/stream.cpp', 'utility/stream.hpp', 'utility/stream.cpp', 'utility/stream.hpp',
@ -185,7 +187,6 @@ libvmime_messaging_sources = [
'messaging/events.cpp', 'messaging/events.hpp', 'messaging/events.cpp', 'messaging/events.hpp',
'messaging/folder.cpp', 'messaging/folder.hpp', 'messaging/folder.cpp', 'messaging/folder.hpp',
'messaging/message.cpp', 'messaging/message.hpp', 'messaging/message.cpp', 'messaging/message.hpp',
'messaging/progressionListener.hpp',
'messaging/service.cpp', 'messaging/service.hpp', 'messaging/service.cpp', 'messaging/service.hpp',
'messaging/serviceFactory.cpp', 'messaging/serviceFactory.hpp', 'messaging/serviceFactory.cpp', 'messaging/serviceFactory.hpp',
'messaging/serviceInfos.hpp', 'messaging/serviceInfos.hpp',
@ -232,6 +233,12 @@ libvmime_messaging_proto_sources = [
'messaging/maildir/maildirMessage.cpp', 'messaging/maildir/maildirMessage.hpp', 'messaging/maildir/maildirMessage.cpp', 'messaging/maildir/maildirMessage.hpp',
'messaging/maildir/maildirUtils.cpp', 'messaging/maildir/maildirUtils.hpp' 'messaging/maildir/maildirUtils.cpp', 'messaging/maildir/maildirUtils.hpp'
] ]
],
[
'sendmail',
[
'messaging/sendmail/sendmailTransport.cpp', 'messaging/sendmail/sendmailTransport.hpp'
]
] ]
] ]
@ -413,7 +420,11 @@ TargetSignatures('build')
############# #############
# Try to guess some default values # Try to guess some default values
# TODO defaultSendmailPath = WhereIs("sendmail")
if defaultSendmailPath == None:
defaultSendmailPath = ''
# Command line options # Command line options
opts = Options('options.cache') opts = Options('options.cache')
@ -453,8 +464,8 @@ opts.AddOptions(
'Specifies which protocols to build into the library.\n' 'Specifies which protocols to build into the library.\n'
+ 'This option has no effect if "with_messaging" is not activated.\n' + 'This option has no effect if "with_messaging" is not activated.\n'
+ 'Separate protocols with spaces; string must be quoted with ".\n' + 'Separate protocols with spaces; string must be quoted with ".\n'
+ 'Currently available protocols: pop3, smtp, imap, maildir.', + 'Currently available protocols: pop3, smtp, imap, maildir, sendmail.',
'"pop3 smtp imap maildir"' '"pop3 smtp imap maildir sendmail"'
), ),
( (
'with_platforms', 'with_platforms',
@ -466,6 +477,11 @@ opts.AddOptions(
+ 'Currently available platform handlers: posix.', + 'Currently available platform handlers: posix.',
'"posix"' '"posix"'
), ),
(
'sendmail_path',
'Specifies the path to sendmail.',
defaultSendmailPath
),
EnumOption( EnumOption(
'with_wide_char_support', 'with_wide_char_support',
'Support for wide characters (rarely used, should be set to "no")', 'Support for wide characters (rarely used, should be set to "no")',
@ -517,6 +533,7 @@ opts.AddOptions(
) )
############################### ###############################
# Configuration Environment # # Configuration Environment #
############################### ###############################
@ -583,20 +600,6 @@ for platform in re.split('\W+', string.replace(env['with_platforms'], '"', '')):
if len(platform) >= 1: if len(platform) >= 1:
platforms.append(platform) platforms.append(platform)
# Show configuration summary
print ""
print "+=================+"
print "| CONFIGURATION |"
print "+=================+"
print ""
print "Installation prefix : " + env['prefix']
print "Debugging mode : " + env['debug']
print "Messaging support : " + env['with_messaging']
if env['with_messaging'] == 'yes':
print " * protocols : " + env['with_messaging_protocols']
print "File-system support : " + env['with_filesystem']
print "Platform handlers : " + env['with_platforms']
print ""
######################## ########################
@ -609,6 +612,7 @@ def IsProtocolSupported(protoList, proto):
return 1 return 1
return 0 return 0
# File-system support must be activated when 'maildir' protocol is selected # File-system support must be activated when 'maildir' protocol is selected
if env['with_messaging'] == 'yes': if env['with_messaging'] == 'yes':
if IsProtocolSupported(messaging_protocols, 'maildir'): if IsProtocolSupported(messaging_protocols, 'maildir'):
@ -616,6 +620,48 @@ if env['with_messaging'] == 'yes':
print "ERROR: 'maildir' protocol requires file-system support!\n" print "ERROR: 'maildir' protocol requires file-system support!\n"
Exit(1) Exit(1)
# Sendmail transport is only available on POSIX platforms
if os.name != 'posix':
if IsProtocolSupported(messaging_protocols, 'sendmail'):
print "WARNING: ignoring 'sendmail' support (only available on POSIX platforms)\n"
newProtoList = [ ]
for p in messaging_protocols:
if string.upper(p) != "SENDMAIL":
newProtoList.append(p)
messaging_protocols = newProtoList
# Check sendmail path
if IsProtocolSupported(messaging_protocols, 'sendmail'):
if env['sendmail_path'] == '':
print "ERROR: no path specified for 'sendmail'"
Exit(1)
###########################
# Configuration summary #
###########################
print ""
print "+=================+"
print "| CONFIGURATION |"
print "+=================+"
print ""
print "Installation prefix : " + env['prefix']
print "Debugging mode : " + env['debug']
print "Messaging support : " + env['with_messaging']
if env['with_messaging'] == 'yes':
print " * protocols : " + env['with_messaging_protocols']
print "File-system support : " + env['with_filesystem']
print "Platform handlers : " + env['with_platforms']
if IsProtocolSupported(messaging_protocols, 'sendmail'):
print "Sendmail path : " + env['sendmail_path']
print ""
######################### #########################
# Generate config.hpp # # Generate config.hpp #
@ -724,6 +770,12 @@ for platform in libvmime_platforms_sources:
if not platform in platforms: if not platform in platforms:
config_hpp.write('#define VMIME_BUILTIN_PLATFORM_' + string.upper(platform) + ' 0\n') config_hpp.write('#define VMIME_BUILTIN_PLATFORM_' + string.upper(platform) + ' 0\n')
config_hpp.write('\n')
config_hpp.write('// Miscellaneous flags\n')
if IsProtocolSupported(messaging_protocols, 'sendmail'):
config_hpp.write('#define VMIME_SENDMAIL_PATH "' + env['sendmail_path'] + '"\n')
config_hpp.write(""" config_hpp.write("""
#endif // VMIME_CONFIG_HPP_INCLUDED #endif // VMIME_CONFIG_HPP_INCLUDED
@ -1432,6 +1484,13 @@ x*)
esac esac
#
# System mail
#
AC_PATH_PROG(SENDMAIL, sendmail, /usr/sbin/sendmail, /usr/sbin:/usr/lib)
# #
# Detect some platform-specific stuff # Detect some platform-specific stuff
# #
@ -1629,6 +1688,10 @@ typedef unsigned ${VMIME_TYPE_INT32} vmime_uint32;
configure_in.write(""" configure_in.write("""
" > vmime/config.hpp " > vmime/config.hpp
# Miscellaneous flags
echo "// Miscellaneous flags" >> vmime/config.hpp
echo "#define VMIME_SENDMAIL_PATH \\"$SENDMAIL\\"" >> vmime/config.hpp
echo "" >> vmime/config.hpp
# Additional defines # Additional defines
echo "// Additional defines" >> vmime/config.hpp echo "// Additional defines" >> vmime/config.hpp
@ -1926,7 +1989,7 @@ typedef unsigned int vmime_uint32;
// -- Messaging support // -- Messaging support
#define VMIME_HAVE_MESSAGING_FEATURES 1 #define VMIME_HAVE_MESSAGING_FEATURES 1
// -- Built-in messaging protocols // -- Built-in messaging protocols
#define VMIME_BUILTIN_MESSAGING_PROTOS " pop3 smtp imap maildir" #define VMIME_BUILTIN_MESSAGING_PROTOS "pop3 smtp imap maildir"
#define VMIME_BUILTIN_MESSAGING_PROTO_POP3 1 #define VMIME_BUILTIN_MESSAGING_PROTO_POP3 1
#define VMIME_BUILTIN_MESSAGING_PROTO_SMTP 1 #define VMIME_BUILTIN_MESSAGING_PROTO_SMTP 1
#define VMIME_BUILTIN_MESSAGING_PROTO_IMAP 1 #define VMIME_BUILTIN_MESSAGING_PROTO_IMAP 1

View File

@ -294,6 +294,18 @@ exception* invalid_argument::clone() const { return new invalid_argument(*this);
const string invalid_argument::name() const { return "invalid_argument"; } const string invalid_argument::name() const { return "invalid_argument"; }
//
// system_error
//
system_error::~system_error() throw() { }
system_error::system_error(const string& what, const exception& other)
: exception(what, other) {}
exception* system_error::clone() const { return new system_error(*this); }
const string system_error::name() const { return "system_error"; }
#if VMIME_HAVE_MESSAGING_FEATURES #if VMIME_HAVE_MESSAGING_FEATURES

View File

@ -47,5 +47,10 @@
REGISTER_SERVICE(maildir::maildirStore, maildir); REGISTER_SERVICE(maildir::maildirStore, maildir);
#endif #endif
#if VMIME_BUILTIN_MESSAGING_PROTO_SENDMAIL
#include "vmime/messaging/sendmail/sendmailTransport.hpp"
REGISTER_SERVICE(sendmail::sendmailTransport, sendmail);
#endif
#endif // VMIME_BUILDING_DOC #endif // VMIME_BUILDING_DOC

View File

@ -596,7 +596,7 @@ std::vector <folder*> IMAPFolder::getFolders(const bool recursive)
void IMAPFolder::fetchMessages(std::vector <message*>& msg, const int options, void IMAPFolder::fetchMessages(std::vector <message*>& msg, const int options,
progressionListener* progress) utility::progressionListener* progress)
{ {
if (!m_store) if (!m_store)
throw exceptions::illegal_state("Store disconnected"); throw exceptions::illegal_state("Store disconnected");
@ -1045,7 +1045,7 @@ void IMAPFolder::setMessageFlags(const string& set, const int flags, const int m
void IMAPFolder::addMessage(vmime::message* msg, const int flags, void IMAPFolder::addMessage(vmime::message* msg, const int flags,
vmime::datetime* date, progressionListener* progress) vmime::datetime* date, utility::progressionListener* progress)
{ {
std::ostringstream oss; std::ostringstream oss;
utility::outputStreamAdapter ossAdapter(oss); utility::outputStreamAdapter ossAdapter(oss);
@ -1060,7 +1060,7 @@ void IMAPFolder::addMessage(vmime::message* msg, const int flags,
void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int flags, void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int flags,
vmime::datetime* date, progressionListener* progress) vmime::datetime* date, utility::progressionListener* progress)
{ {
if (!m_store) if (!m_store)
throw exceptions::illegal_state("Store disconnected"); throw exceptions::illegal_state("Store disconnected");

View File

@ -243,7 +243,7 @@ class IMAPMessage_literalHandler : public IMAPParser::literalHandler
{ {
public: public:
IMAPMessage_literalHandler(utility::outputStream& os, progressionListener* progress) IMAPMessage_literalHandler(utility::outputStream& os, utility::progressionListener* progress)
: m_os(os), m_progress(progress) : m_os(os), m_progress(progress)
{ {
} }
@ -268,7 +268,7 @@ public:
private: private:
utility::outputStream& m_os; utility::outputStream& m_os;
progressionListener* m_progress; utility::progressionListener* m_progress;
}; };
#endif // VMIME_BUILDING_DOC #endif // VMIME_BUILDING_DOC
@ -366,7 +366,7 @@ const header& IMAPMessage::getHeader() const
} }
void IMAPMessage::extract(utility::outputStream& os, progressionListener* progress, void IMAPMessage::extract(utility::outputStream& os, utility::progressionListener* progress,
const int start, const int length) const const int start, const int length) const
{ {
if (!m_folder) if (!m_folder)
@ -377,7 +377,7 @@ void IMAPMessage::extract(utility::outputStream& os, progressionListener* progre
void IMAPMessage::extractPart void IMAPMessage::extractPart
(const part& p, utility::outputStream& os, progressionListener* progress, (const part& p, utility::outputStream& os, utility::progressionListener* progress,
const int start, const int length) const const int start, const int length) const
{ {
if (!m_folder) if (!m_folder)
@ -401,8 +401,9 @@ void IMAPMessage::fetchPartHeader(part& p)
} }
void IMAPMessage::extract(const part* p, utility::outputStream& os, progressionListener* progress, void IMAPMessage::extract(const part* p, utility::outputStream& os,
const int start, const int length, const bool headerOnly) const utility::progressionListener* progress, const int start,
const int length, const bool headerOnly) const
{ {
IMAPMessage_literalHandler literalHandler(os, progress); IMAPMessage_literalHandler literalHandler(os, progress);

View File

@ -839,7 +839,7 @@ void maildirFolder::setMessageFlagsImpl
void maildirFolder::addMessage(vmime::message* msg, const int flags, void maildirFolder::addMessage(vmime::message* msg, const int flags,
vmime::datetime* date, progressionListener* progress) vmime::datetime* date, utility::progressionListener* progress)
{ {
std::ostringstream oss; std::ostringstream oss;
utility::outputStreamAdapter ossAdapter(oss); utility::outputStreamAdapter ossAdapter(oss);
@ -854,7 +854,7 @@ void maildirFolder::addMessage(vmime::message* msg, const int flags,
void maildirFolder::addMessage(utility::inputStream& is, const int size, void maildirFolder::addMessage(utility::inputStream& is, const int size,
const int flags, vmime::datetime* /* date */, progressionListener* progress) const int flags, vmime::datetime* /* date */, utility::progressionListener* progress)
{ {
if (!m_store) if (!m_store)
throw exceptions::illegal_state("Store disconnected"); throw exceptions::illegal_state("Store disconnected");
@ -938,7 +938,8 @@ void maildirFolder::addMessage(utility::inputStream& is, const int size,
void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath,
const utility::file::path& curDirPath, const utility::file::path::component& filename, const utility::file::path& curDirPath, const utility::file::path::component& filename,
utility::inputStream& is, const utility::stream::size_type size, progressionListener* progress) utility::inputStream& is, const utility::stream::size_type size,
utility::progressionListener* progress)
{ {
utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory();
@ -1295,7 +1296,7 @@ store* maildirFolder::getStore()
void maildirFolder::fetchMessages(std::vector <message*>& msg, void maildirFolder::fetchMessages(std::vector <message*>& msg,
const int options, progressionListener* progress) const int options, utility::progressionListener* progress)
{ {
if (!m_store) if (!m_store)
throw exceptions::illegal_state("Store disconnected"); throw exceptions::illegal_state("Store disconnected");

View File

@ -309,14 +309,14 @@ void maildirMessage::setFlags(const int flags, const int mode)
void maildirMessage::extract(utility::outputStream& os, void maildirMessage::extract(utility::outputStream& os,
progressionListener* progress, const int start, const int length) const utility::progressionListener* progress, const int start, const int length) const
{ {
extractImpl(os, progress, 0, m_size, start, length); extractImpl(os, progress, 0, m_size, start, length);
} }
void maildirMessage::extractPart(const part& p, utility::outputStream& os, void maildirMessage::extractPart(const part& p, utility::outputStream& os,
progressionListener* progress, const int start, const int length) const utility::progressionListener* progress, const int start, const int length) const
{ {
const maildirPart& mp = dynamic_cast <const maildirPart&>(p); const maildirPart& mp = dynamic_cast <const maildirPart&>(p);
@ -324,7 +324,7 @@ void maildirMessage::extractPart(const part& p, utility::outputStream& os,
} }
void maildirMessage::extractImpl(utility::outputStream& os, progressionListener* progress, void maildirMessage::extractImpl(utility::outputStream& os, utility::progressionListener* progress,
const int start, const int length, const int partialStart, const int partialLength) const const int start, const int length, const int partialStart, const int partialLength) const
{ {
utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory();

View File

@ -293,7 +293,7 @@ std::vector <folder*> POP3Folder::getFolders(const bool /* recursive */)
void POP3Folder::fetchMessages(std::vector <message*>& msg, const int options, void POP3Folder::fetchMessages(std::vector <message*>& msg, const int options,
progressionListener* progress) utility::progressionListener* progress)
{ {
if (!m_store) if (!m_store)
throw exceptions::illegal_state("Store disconnected"); throw exceptions::illegal_state("Store disconnected");
@ -681,14 +681,14 @@ void POP3Folder::rename(const folder::path& /* newPath */)
void POP3Folder::addMessage(vmime::message* /* msg */, const int /* flags */, void POP3Folder::addMessage(vmime::message* /* msg */, const int /* flags */,
vmime::datetime* /* date */, progressionListener* /* progress */) vmime::datetime* /* date */, utility::progressionListener* /* progress */)
{ {
throw exceptions::operation_not_supported(); throw exceptions::operation_not_supported();
} }
void POP3Folder::addMessage(utility::inputStream& /* is */, const int /* size */, const int /* flags */, void POP3Folder::addMessage(utility::inputStream& /* is */, const int /* size */, const int /* flags */,
vmime::datetime* /* date */, progressionListener* /* progress */) vmime::datetime* /* date */, utility::progressionListener* /* progress */)
{ {
throw exceptions::operation_not_supported(); throw exceptions::operation_not_supported();
} }

View File

@ -110,8 +110,8 @@ const header& POP3Message::getHeader() const
} }
void POP3Message::extract(utility::outputStream& os, progressionListener* progress, void POP3Message::extract(utility::outputStream& os,
const int start, const int length) const utility::progressionListener* progress, const int start, const int length) const
{ {
if (!m_folder) if (!m_folder)
throw exceptions::illegal_state("Folder closed"); throw exceptions::illegal_state("Folder closed");
@ -146,7 +146,8 @@ void POP3Message::extract(utility::outputStream& os, progressionListener* progre
void POP3Message::extractPart void POP3Message::extractPart
(const part& /* p */, utility::outputStream& /* os */, progressionListener* /* progress */, (const part& /* p */, utility::outputStream& /* os */,
utility::progressionListener* /* progress */,
const int /* start */, const int /* length */) const const int /* start */, const int /* length */) const
{ {
throw exceptions::operation_not_supported(); throw exceptions::operation_not_supported();

View File

@ -311,7 +311,7 @@ void POP3Store::sendRequest(const string& buffer, const bool end)
void POP3Store::readResponse(string& buffer, const bool multiLine, void POP3Store::readResponse(string& buffer, const bool multiLine,
progressionListener* progress) utility::progressionListener* progress)
{ {
bool foundTerminator = false; bool foundTerminator = false;
int current = 0, total = 0; int current = 0, total = 0;
@ -406,8 +406,8 @@ void POP3Store::readResponse(string& buffer, const bool multiLine,
} }
void POP3Store::readResponse(utility::outputStream& os, progressionListener* progress, void POP3Store::readResponse(utility::outputStream& os,
const int predictedSize) utility::progressionListener* progress, const int predictedSize)
{ {
bool foundTerminator = false; bool foundTerminator = false;
int current = 0, total = predictedSize; int current = 0, total = predictedSize;

View File

@ -0,0 +1,387 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "vmime/messaging/sendmail/sendmailTransport.hpp"
#include "vmime/exception.hpp"
#include "vmime/platformDependant.hpp"
#include "vmime/message.hpp"
#include "vmime/mailboxList.hpp"
#include "vmime/messaging/authHelper.hpp"
#include "vmime/utility/filteredStream.hpp"
#if VMIME_BUILTIN_PLATFORM_POSIX
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
namespace vmime {
namespace messaging {
namespace sendmail {
sendmailTransport::sendmailTransport(session* sess, authenticator* auth)
: transport(sess, getInfosInstance(), auth), m_connected(false)
{
}
sendmailTransport::~sendmailTransport()
{
if (isConnected())
disconnect();
}
const string sendmailTransport::getProtocolName() const
{
return "sendmail";
}
void sendmailTransport::connect()
{
if (isConnected())
throw exceptions::already_connected();
// Use the specified path for 'sendmail' or a default one if no path is specified
m_sendmailPath = getSession()->getProperties().getProperty
(sm_infos.getPropertyPrefix() + "binpath", string(VMIME_SENDMAIL_PATH));
m_connected = true;
}
const bool sendmailTransport::isConnected() const
{
return (m_connected);
}
void sendmailTransport::disconnect()
{
if (!isConnected())
throw exceptions::not_connected();
internalDisconnect();
}
void sendmailTransport::internalDisconnect()
{
m_connected = false;
}
void sendmailTransport::noop()
{
// Do nothing
}
void sendmailTransport::send
(const mailbox& expeditor, const mailboxList& recipients,
utility::inputStream& is, const utility::stream::size_type size,
utility::progressionListener* progress)
{
// If no recipient/expeditor was found, throw an exception
if (recipients.isEmpty())
throw exceptions::no_recipient();
else if (expeditor.isEmpty())
throw exceptions::no_expeditor();
// Construct the argument list
std::vector <string> args;
args.push_back("-i");
args.push_back("-f");
args.push_back(expeditor.getEmail());
args.push_back("--");
for (int i = 0 ; i < recipients.getMailboxCount() ; ++i)
args.push_back(recipients.getMailboxAt(i)->getEmail());
// Call sendmail
try
{
internalSend(args, is, size, progress);
}
catch (vmime::exception& e)
{
throw exceptions::command_error("SEND", "", "sendmail failed", e);
}
}
static const string getSignalMessage(const int num)
{
switch (num)
{
case SIGHUP: return "SIGHUP";
case SIGINT: return "SIGINT";
case SIGQUIT: return "SIGQUIT";
case SIGILL: return "SIGILL";
case SIGABRT: return "SIGABRT";
case SIGFPE: return "SIGFPE";
case SIGKILL: return "SIGKILL";
case SIGSEGV: return "SIGSEGV";
case SIGPIPE: return "SIGPIPE";
case SIGALRM: return "SIGALRM";
case SIGTERM: return "SIGTERM";
case SIGUSR1: return "SIGUSR1";
case SIGUSR2: return "SIGUSR2";
case SIGCHLD: return "SIGCHLD";
case SIGCONT: return "SIGCONT";
case SIGSTOP: return "SIGSTOP";
case SIGTSTP: return "SIGTSTP";
case SIGTTIN: return "SIGTTIN";
case SIGTTOU: return "SIGTTOU";
}
return "(unknown)";
}
static const string getErrorMessage(const int num)
{
#ifdef strerror_r
char res[256];
res[0] = '\0';
strerror_r(num, res, sizeof(res));
return string(res);
#else
return string(strerror(num));
#endif
}
#ifndef VMIME_BUILDING_DOC
// Output stream adapter for UNIX pipe
class outputStreamPipeAdapter : public utility::outputStream
{
public:
outputStreamPipeAdapter(const int desc)
: m_desc(desc)
{
}
void write(const value_type* const data, const size_type count)
{
if (::write(m_desc, data, count) == -1)
{
const string errorMsg = getErrorMessage(errno);
throw exceptions::system_error(errorMsg);
}
}
private:
int m_desc;
};
#endif // VMIME_BUILDING_DOC
// The following code is highly inspired and adapted from the 'sendmail'
// provider module in Evolution data server code.
//
// Original authors: Dan Winship <danw@ximian.com>
// Copyright 2000 Ximian, Inc. (www.ximian.com)
void sendmailTransport::internalSend
(const std::vector <string> args, utility::inputStream& is,
const utility::stream::size_type size, utility::progressionListener* progress)
{
// Construct C-style argument array
const char** argv = new const char*[args.size() + 2];
argv[0] = "sendmail";
argv[args.size()] = NULL;
for (unsigned int i = 0 ; i < args.size() ; ++i)
argv[i + 1] = args[i].c_str();
// Create a pipe to communicate with sendmail
int fd[2];
if (pipe(fd) == -1)
{
throw exceptions::system_error(getErrorMessage(errno));
}
// Block SIGCHLD so the calling application doesn't notice
// sendmail exiting before we do
sigset_t mask, oldMask;
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, &oldMask);
// Spawn 'sendmail' process
pid_t pid = fork();
if (pid == -1) // error
{
const string errorMsg = getErrorMessage(errno);
sigprocmask(SIG_SETMASK, &oldMask, NULL);
close(fd[0]);
close(fd[1]);
throw exceptions::system_error(errorMsg);
}
else if (pid == 0) // child process
{
dup2(fd[0], STDIN_FILENO);
close(fd[1]);
execv(m_sendmailPath.c_str(), const_cast <char**>(argv));
_exit(255);
}
close(fd[0]);
// Copy message data from input stream to output pipe
try
{
outputStreamPipeAdapter pos(fd[1]);
// Workaround for lame sendmail implementations that
// can't handle CRLF eoln sequences: we transform CRLF
// sequences into LF characters.
utility::CRLFToLFFilteredOutputStream fos(pos);
// TODO: remove 'Bcc:' field from message header
utility::bufferedStreamCopy(is, fos, size, progress);
}
catch (exception& e)
{
close(fd[1]);
int wstat;
while (waitpid(pid, &wstat, 0) == -1 && errno == EINTR)
;
sigprocmask(SIG_SETMASK, &oldMask, NULL);
throw;
}
close(fd[1]);
// Wait for sendmail to exit
int wstat;
while (waitpid(pid, &wstat, 0) == -1 && errno == EINTR)
;
sigprocmask(SIG_SETMASK, &oldMask, NULL);
if (!WIFEXITED(wstat))
{
throw exceptions::system_error("sendmail exited with signal "
+ getSignalMessage(WTERMSIG(wstat)) + ", mail not sent");
}
else if (WEXITSTATUS(wstat) != 0)
{
if (WEXITSTATUS(wstat) == 255)
{
std::ostringstream oss;
oss << "Could not execute '" << m_sendmailPath;
oss << "', mail not sent";
throw exceptions::system_error(oss.str());
}
else
{
std::ostringstream oss;
oss << "sendmail exited with status " << WEXITSTATUS(wstat);
oss << ", mail not sent";
throw exceptions::system_error(oss.str());
}
}
}
// Service infos
sendmailTransport::_infos sendmailTransport::sm_infos;
const serviceInfos& sendmailTransport::getInfosInstance()
{
return (sm_infos);
}
const serviceInfos& sendmailTransport::getInfos() const
{
return (sm_infos);
}
const port_t sendmailTransport::_infos::getDefaultPort() const
{
return (0);
}
const string sendmailTransport::_infos::getPropertyPrefix() const
{
return "transport.sendmail.";
}
const std::vector <string> sendmailTransport::_infos::getAvailableProperties() const
{
std::vector <string> list;
// Path to sendmail (override default)
list.push_back("binpath");
return (list);
}
} // sendmail
} // messaging
} // vmime
#endif // VMIME_BUILTIN_PLATFORM_POSIX

View File

@ -26,6 +26,8 @@
#include "vmime/messaging/authHelper.hpp" #include "vmime/messaging/authHelper.hpp"
#include "vmime/utility/filteredStream.hpp"
namespace vmime { namespace vmime {
namespace messaging { namespace messaging {
@ -259,7 +261,7 @@ void SMTPTransport::noop()
void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients, void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients,
utility::inputStream& is, const utility::stream::size_type size, utility::inputStream& is, const utility::stream::size_type size,
progressionListener* progress) utility::progressionListener* progress)
{ {
// If no recipient/expeditor was found, throw an exception // If no recipient/expeditor was found, throw an exception
if (recipients.isEmpty()) if (recipients.isEmpty())
@ -304,63 +306,13 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients
throw exceptions::command_error("DATA", response); throw exceptions::command_error("DATA", response);
} }
int current = 0, total = size; // Stream copy with "\n." to "\n.." transformation
utility::outputStreamSocketAdapter sos(*m_socket);
utility::dotFilteredOutputStream fos(sos);
if (progress) utility::bufferedStreamCopy(is, fos, size, progress);
progress->start(total);
char buffer[65536];
char previousChar = '\0';
while (!is.eof())
{
const int read = is.read(buffer, sizeof(buffer));
// Transform '.' into '..' at the beginning of a line
char* start = buffer;
char* end = buffer + read;
char* pos = buffer;
while ((pos = std::find(pos, end, '.')) != end)
{
// '\n' in the previous buffer, '.' in the current one
if (pos == buffer && previousChar == '\n')
{
m_socket->sendRaw(".", 1);
}
// Both '\n' and '.' are in the current buffer
else if (pos > buffer && *(pos - 1) == '\n')
{
m_socket->sendRaw(start, pos - start);
m_socket->sendRaw(".", 1);
start = pos;
}
++pos;
}
if (read > 0)
previousChar = buffer[read - 1];
else
previousChar = '\0';
// Send the remaining data
m_socket->sendRaw(start, end - start);
current += read;
// Notify progression
if (progress)
{
total = std::max(total, current);
progress->progress(current, total);
}
}
if (progress)
progress->stop(total);
// Send end-of-data delimiter
m_socket->sendRaw("\r\n.\r\n", 5); m_socket->sendRaw("\r\n.\r\n", 5);
readResponse(response); readResponse(response);

View File

@ -47,7 +47,7 @@ static void extractMailboxes
} }
void transport::send(vmime::message* msg, progressionListener* progress) void transport::send(vmime::message* msg, utility::progressionListener* progress)
{ {
// Extract expeditor // Extract expeditor
mailbox expeditor; mailbox expeditor;

View File

@ -0,0 +1,115 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "vmime/utility/filteredStream.hpp"
namespace vmime {
namespace utility {
// dotFilteredOutputStream
dotFilteredOutputStream::dotFilteredOutputStream(outputStream& os)
: m_stream(os)
{
}
outputStream& dotFilteredOutputStream::getNextOutputStream()
{
return (m_stream);
}
void dotFilteredOutputStream::write
(const value_type* const data, const size_type count)
{
const value_type* pos = data;
const value_type* end = data + count;
const value_type* start = data;
// Replace "\n." with "\n.."
while ((pos = std::find(pos, end, '.')) != end)
{
const value_type previousChar =
(pos == data ? m_previousChar : *(pos - 1));
if (previousChar == '\n')
{
m_stream.write(start, pos - data);
m_stream.write("..", 2);
start = pos + 1;
}
++pos;
}
m_stream.write(start, end - start);
m_previousChar = data[count - 1];
}
// CRLFToLFFilteredOutputStream
CRLFToLFFilteredOutputStream::CRLFToLFFilteredOutputStream(outputStream& os)
: m_stream(os)
{
}
outputStream& CRLFToLFFilteredOutputStream::getNextOutputStream()
{
return (m_stream);
}
void CRLFToLFFilteredOutputStream::write
(const value_type* const data, const size_type count)
{
const value_type* pos = data;
const value_type* end = data + count;
const value_type* start = data;
// Replace "\r\n" (CRLF) with "\n" (LF)
while ((pos = std::find(pos, end, '\n')) != end)
{
const value_type previousChar =
(pos == data ? m_previousChar : *(pos - 1));
if (previousChar == '\r')
{
m_stream.write(start, pos - 1 - data); // do not write \r
m_stream.write("\n", 1);
start = pos + 1;
}
++pos;
}
m_stream.write(start, end - start);
m_previousChar = data[count - 1];
}
} // utility
} // vmime

View File

@ -23,6 +23,10 @@
#include <algorithm> // for std::copy #include <algorithm> // for std::copy
#include <iterator> // for std::back_inserter #include <iterator> // for std::back_inserter
#if VMIME_HAVE_MESSAGING_FEATURES
#include "vmime/messaging/socket.hpp"
#endif
namespace vmime { namespace vmime {
namespace utility { namespace utility {
@ -45,10 +49,20 @@ outputStream& operator<<(outputStream& os, const string& str)
const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os) const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os)
{
return bufferedStreamCopy(is, os, 0, NULL);
}
const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
const stream::size_type length, progressionListener* progress)
{ {
stream::value_type buffer[65536]; stream::value_type buffer[65536];
stream::size_type total = 0; stream::size_type total = 0;
if (progress != NULL)
progress->start(length);
while (!is.eof()) while (!is.eof())
{ {
const stream::size_type read = is.read(buffer, sizeof(buffer)); const stream::size_type read = is.read(buffer, sizeof(buffer));
@ -57,9 +71,15 @@ const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os)
{ {
os.write(buffer, read); os.write(buffer, read);
total += read; total += read;
if (progress != NULL)
progress->progress(total, std::max(total, length));
} }
} }
if (progress != NULL)
progress->stop(total);
return (total); return (total);
} }
@ -299,5 +319,28 @@ const stream::size_type inputStreamPointerAdapter::skip(const size_type count)
} }
// outputStreamSocketAdapter
#ifdef VMIME_HAVE_MESSAGING_FEATURES
outputStreamSocketAdapter::outputStreamSocketAdapter(messaging::socket& sok)
: m_socket(sok)
{
}
void outputStreamSocketAdapter::write
(const value_type* const data, const size_type count)
{
m_socket.sendRaw(data, count);
}
#endif // VMIME_HAVE_MESSAGING_FEATURES
} // utility } // utility
} // vmime } // vmime

View File

@ -311,6 +311,21 @@ public:
}; };
/** Underlying operating system error.
*/
class system_error : public vmime::exception
{
public:
system_error(const string& what, const exception& other = NO_EXCEPTION);
~system_error() throw();
exception* clone() const;
const string name() const;
};
#if VMIME_HAVE_MESSAGING_FEATURES #if VMIME_HAVE_MESSAGING_FEATURES

View File

@ -25,11 +25,13 @@
#include "vmime/types.hpp" #include "vmime/types.hpp"
#include "vmime/dateTime.hpp" #include "vmime/dateTime.hpp"
#include "vmime/messaging/progressionListener.hpp"
#include "vmime/messaging/message.hpp" #include "vmime/messaging/message.hpp"
#include "vmime/messaging/events.hpp" #include "vmime/messaging/events.hpp"
#include "vmime/utility/path.hpp" #include "vmime/utility/path.hpp"
#include "vmime/utility/stream.hpp" #include "vmime/utility/stream.hpp"
#include "vmime/utility/progressionListener.hpp"
namespace vmime { namespace vmime {
@ -244,7 +246,7 @@ public:
* @param date date/time for the new message (if NULL, the current time is used) * @param date date/time for the new message (if NULL, the current time is used)
* @param progress progression listener, or NULL if not used * @param progress progression listener, or NULL if not used
*/ */
virtual void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL) = 0; virtual void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL) = 0;
/** Add a message to this folder. /** Add a message to this folder.
* *
@ -254,7 +256,7 @@ public:
* @param date date/time for the new message (if NULL, the current time is used) * @param date date/time for the new message (if NULL, the current time is used)
* @param progress progression listener, or NULL if not used * @param progress progression listener, or NULL if not used
*/ */
virtual void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL) = 0; virtual void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL) = 0;
/** Copy a message from this folder to another folder. /** Copy a message from this folder to another folder.
* *
@ -328,7 +330,7 @@ public:
* @param options objects to fetch (combination of folder::FetchOptions flags) * @param options objects to fetch (combination of folder::FetchOptions flags)
* @param progress progression listener, or NULL if not used * @param progress progression listener, or NULL if not used
*/ */
virtual void fetchMessages(std::vector <message*>& msg, const int options, progressionListener* progress = NULL) = 0; virtual void fetchMessages(std::vector <message*>& msg, const int options, utility::progressionListener* progress = NULL) = 0;
/** Fetch objects for the specified message. /** Fetch objects for the specified message.
* *

View File

@ -91,8 +91,8 @@ public:
void setMessageFlags(const int from, const int to, const int flags, const int mode = message::FLAG_MODE_SET); void setMessageFlags(const int from, const int to, const int flags, const int mode = message::FLAG_MODE_SET);
void setMessageFlags(const std::vector <int>& nums, const int flags, const int mode = message::FLAG_MODE_SET); void setMessageFlags(const std::vector <int>& nums, const int flags, const int mode = message::FLAG_MODE_SET);
void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL); void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL);
void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL); void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL);
void copyMessage(const folder::path& dest, const int num); void copyMessage(const folder::path& dest, const int num);
void copyMessages(const folder::path& dest, const int from = 1, const int to = -1); void copyMessages(const folder::path& dest, const int from = 1, const int to = -1);
@ -108,7 +108,7 @@ public:
store* getStore(); store* getStore();
void fetchMessages(std::vector <message*>& msg, const int options, progressionListener* progress = NULL); void fetchMessages(std::vector <message*>& msg, const int options, utility::progressionListener* progress = NULL);
void fetchMessage(message* msg, const int options); void fetchMessage(message* msg, const int options);
const int getFetchCapabilities() const; const int getFetchCapabilities() const;

View File

@ -64,8 +64,8 @@ public:
const int getFlags() const; const int getFlags() const;
void setFlags(const int flags, const int mode = FLAG_MODE_SET); void setFlags(const int flags, const int mode = FLAG_MODE_SET);
void extract(utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const; void extract(utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void extractPart(const part& p, utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const; void extractPart(const part& p, utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void fetchPartHeader(part& p); void fetchPartHeader(part& p);
@ -75,7 +75,7 @@ private:
void processFetchResponse(const int options, const IMAPParser::msg_att* msgAtt); void processFetchResponse(const int options, const IMAPParser::msg_att* msgAtt);
void extract(const part* p, utility::outputStream& os, progressionListener* progress, const int start, const int length, const bool headerOnly) const; void extract(const part* p, utility::outputStream& os, utility::progressionListener* progress, const int start, const int length, const bool headerOnly) const;
void convertAddressList(const IMAPParser::address_list& src, mailboxList& dest); void convertAddressList(const IMAPParser::address_list& src, mailboxList& dest);

View File

@ -28,13 +28,13 @@
#include "vmime/utility/smartPtr.hpp" #include "vmime/utility/smartPtr.hpp"
#include "vmime/utility/stringUtils.hpp" #include "vmime/utility/stringUtils.hpp"
#include "vmime/utility/progressionListener.hpp"
#include "vmime/encoderB64.hpp" #include "vmime/encoderB64.hpp"
#include "vmime/encoderQP.hpp" #include "vmime/encoderQP.hpp"
#include "vmime/platformDependant.hpp" #include "vmime/platformDependant.hpp"
#include "vmime/messaging/progressionListener.hpp"
#include "vmime/messaging/timeoutHandler.hpp" #include "vmime/messaging/timeoutHandler.hpp"
#include "vmime/messaging/socket.hpp" #include "vmime/messaging/socket.hpp"
@ -135,7 +135,7 @@ public:
{ {
protected: protected:
target(class progressionListener* progress) : m_progress(progress) {} target(utility::progressionListener* progress) : m_progress(progress) {}
target(const target&) {} target(const target&) {}
public: public:
@ -143,13 +143,13 @@ public:
virtual ~target() { } virtual ~target() { }
class progressionListener* progressionListener() { return (m_progress); } utility::progressionListener* progressionListener() { return (m_progress); }
virtual void putData(const string& chunk) = 0; virtual void putData(const string& chunk) = 0;
private: private:
class progressionListener* m_progress; utility::progressionListener* m_progress;
}; };
@ -158,7 +158,7 @@ public:
{ {
public: public:
targetString(class progressionListener* progress, vmime::string& str) targetString(utility::progressionListener* progress, vmime::string& str)
: target(progress), m_string(str) { } : target(progress), m_string(str) { }
const vmime::string& string() const { return (m_string); } const vmime::string& string() const { return (m_string); }
@ -181,7 +181,7 @@ public:
{ {
public: public:
targetStream(class progressionListener* progress, utility::outputStream& stream) targetStream(utility::progressionListener* progress, utility::outputStream& stream)
: target(progress), m_stream(stream) { } : target(progress), m_stream(stream) { }
const utility::outputStream& stream() const { return (m_stream); } const utility::outputStream& stream() const { return (m_stream); }
@ -809,7 +809,7 @@ public:
m_value = "[literal-handler]"; m_value = "[literal-handler]";
const string::size_type length = text->value().length(); const string::size_type length = text->value().length();
progressionListener* progress = target->progressionListener(); utility::progressionListener* progress = target->progressionListener();
if (progress) if (progress)
{ {
@ -4914,7 +4914,7 @@ private:
IMAPTag* m_tag; IMAPTag* m_tag;
socket* m_socket; socket* m_socket;
progressionListener* m_progress; utility::progressionListener* m_progress;
literalHandler* m_literalHandler; literalHandler* m_literalHandler;

View File

@ -91,8 +91,8 @@ public:
void setMessageFlags(const int from, const int to, const int flags, const int mode = message::FLAG_MODE_SET); void setMessageFlags(const int from, const int to, const int flags, const int mode = message::FLAG_MODE_SET);
void setMessageFlags(const std::vector <int>& nums, const int flags, const int mode = message::FLAG_MODE_SET); void setMessageFlags(const std::vector <int>& nums, const int flags, const int mode = message::FLAG_MODE_SET);
void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL); void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL);
void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL); void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL);
void copyMessage(const folder::path& dest, const int num); void copyMessage(const folder::path& dest, const int num);
void copyMessages(const folder::path& dest, const int from = 1, const int to = -1); void copyMessages(const folder::path& dest, const int from = 1, const int to = -1);
@ -108,7 +108,7 @@ public:
store* getStore(); store* getStore();
void fetchMessages(std::vector <message*>& msg, const int options, progressionListener* progress = NULL); void fetchMessages(std::vector <message*>& msg, const int options, utility::progressionListener* progress = NULL);
void fetchMessage(message* msg, const int options); void fetchMessage(message* msg, const int options);
const int getFetchCapabilities() const; const int getFetchCapabilities() const;
@ -132,7 +132,7 @@ private:
void setMessageFlagsImpl(const std::vector <int>& nums, const int flags, const int mode); void setMessageFlagsImpl(const std::vector <int>& nums, const int flags, const int mode);
void copyMessagesImpl(const folder::path& dest, const std::vector <int>& nums); void copyMessagesImpl(const folder::path& dest, const std::vector <int>& nums);
void copyMessageImpl(const utility::file::path& tmpDirPath, const utility::file::path& curDirPath, const utility::file::path::component& filename, utility::inputStream& is, const utility::stream::size_type size, progressionListener* progress); void copyMessageImpl(const utility::file::path& tmpDirPath, const utility::file::path& curDirPath, const utility::file::path::component& filename, utility::inputStream& is, const utility::stream::size_type size, utility::progressionListener* progress);
void notifyMessagesCopied(const folder::path& dest); void notifyMessagesCopied(const folder::path& dest);

View File

@ -65,8 +65,8 @@ public:
const int getFlags() const; const int getFlags() const;
void setFlags(const int flags, const int mode = FLAG_MODE_SET); void setFlags(const int flags, const int mode = FLAG_MODE_SET);
void extract(utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const; void extract(utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void extractPart(const part& p, utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const; void extractPart(const part& p, utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void fetchPartHeader(part& p); void fetchPartHeader(part& p);
@ -78,7 +78,7 @@ private:
header& getOrCreateHeader(); header& getOrCreateHeader();
void extractImpl(utility::outputStream& os, progressionListener* progress, const int start, const int length, const int partialStart, const int partialLength) const; void extractImpl(utility::outputStream& os, utility::progressionListener* progress, const int start, const int length, const int partialStart, const int partialLength) const;
maildirFolder* m_folder; maildirFolder* m_folder;

View File

@ -22,7 +22,8 @@
#include "vmime/header.hpp" #include "vmime/header.hpp"
#include "vmime/messaging/progressionListener.hpp"
#include "vmime/utility/progressionListener.hpp"
#include "vmime/utility/stream.hpp" #include "vmime/utility/stream.hpp"
@ -257,7 +258,7 @@ public:
* @param length number of bytes to retrieve (used for partial fetch) * @param length number of bytes to retrieve (used for partial fetch)
*/ */
virtual void extract(utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const = 0; virtual void extract(utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const = 0;
/** Extract the specified (MIME) part of the message (header + contents). /** Extract the specified (MIME) part of the message (header + contents).
* *
@ -269,7 +270,7 @@ public:
* @param start index of the first byte to retrieve (used for partial fetch) * @param start index of the first byte to retrieve (used for partial fetch)
* @param length number of bytes to retrieve (used for partial fetch) * @param length number of bytes to retrieve (used for partial fetch)
*/ */
virtual void extractPart(const part& p, utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const = 0; virtual void extractPart(const part& p, utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const = 0;
/** Fetch the MIME header for the specified part. /** Fetch the MIME header for the specified part.
* *

View File

@ -90,8 +90,8 @@ public:
void setMessageFlags(const int from, const int to, const int flags, const int mode = message::FLAG_MODE_SET); void setMessageFlags(const int from, const int to, const int flags, const int mode = message::FLAG_MODE_SET);
void setMessageFlags(const std::vector <int>& nums, const int flags, const int mode = message::FLAG_MODE_SET); void setMessageFlags(const std::vector <int>& nums, const int flags, const int mode = message::FLAG_MODE_SET);
void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL); void addMessage(vmime::message* msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL);
void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, progressionListener* progress = NULL); void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressionListener* progress = NULL);
void copyMessage(const folder::path& dest, const int num); void copyMessage(const folder::path& dest, const int num);
void copyMessages(const folder::path& dest, const int from = 1, const int to = -1); void copyMessages(const folder::path& dest, const int from = 1, const int to = -1);
@ -107,7 +107,7 @@ public:
store* getStore(); store* getStore();
void fetchMessages(std::vector <message*>& msg, const int options, progressionListener* progress = NULL); void fetchMessages(std::vector <message*>& msg, const int options, utility::progressionListener* progress = NULL);
void fetchMessage(message* msg, const int options); void fetchMessage(message* msg, const int options);
const int getFetchCapabilities() const; const int getFetchCapabilities() const;

View File

@ -64,8 +64,8 @@ public:
const int getFlags() const; const int getFlags() const;
void setFlags(const int flags, const int mode = FLAG_MODE_SET); void setFlags(const int flags, const int mode = FLAG_MODE_SET);
void extract(utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const; void extract(utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void extractPart(const part& p, utility::outputStream& os, progressionListener* progress = NULL, const int start = 0, const int length = -1) const; void extractPart(const part& p, utility::outputStream& os, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void fetchPartHeader(part& p); void fetchPartHeader(part& p);

View File

@ -74,8 +74,8 @@ private:
static void stripResponseCode(const string& buffer, string& result); static void stripResponseCode(const string& buffer, string& result);
void sendRequest(const string& buffer, const bool end = true); void sendRequest(const string& buffer, const bool end = true);
void readResponse(string& buffer, const bool multiLine, progressionListener* progress = NULL); void readResponse(string& buffer, const bool multiLine, utility::progressionListener* progress = NULL);
void readResponse(utility::outputStream& os, progressionListener* progress = NULL, const int predictedSize = 0); void readResponse(utility::outputStream& os, utility::progressionListener* progress = NULL, const int predictedSize = 0);
static const bool checkTerminator(string& buffer, const bool multiLine); static const bool checkTerminator(string& buffer, const bool multiLine);
static const bool checkOneTerminator(string& buffer, const string& term); static const bool checkOneTerminator(string& buffer, const string& term);

View File

@ -0,0 +1,98 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_MESSAGING_SENDMAIL_SENDMAILTRANSPORT_HPP_INCLUDED
#define VMIME_MESSAGING_SENDMAIL_SENDMAILTRANSPORT_HPP_INCLUDED
#include "vmime/config.hpp"
#include "vmime/messaging/transport.hpp"
#include "vmime/messaging/socket.hpp"
#include "vmime/messaging/timeoutHandler.hpp"
#if VMIME_BUILTIN_PLATFORM_POSIX
namespace vmime {
namespace messaging {
namespace sendmail {
/** Sendmail local transport service.
*/
class sendmailTransport : public transport
{
public:
sendmailTransport(session* sess, authenticator* auth);
~sendmailTransport();
const string getProtocolName() const;
static const serviceInfos& getInfosInstance();
const serviceInfos& getInfos() const;
void connect();
const bool isConnected() const;
void disconnect();
void noop();
void send(const mailbox& expeditor, const mailboxList& recipients, utility::inputStream& is, const utility::stream::size_type size, utility::progressionListener* progress = NULL);
private:
void internalDisconnect();
void internalSend(const std::vector <string> args, utility::inputStream& is,
const utility::stream::size_type size, utility::progressionListener* progress);
string m_sendmailPath;
bool m_connected;
// Service infos
class _infos : public serviceInfos
{
public:
const port_t getDefaultPort() const;
const string getPropertyPrefix() const;
const std::vector <string> getAvailableProperties() const;
};
static _infos sm_infos;
};
} // sendmail
} // messaging
} // vmime
#endif // VMIME_BUILTIN_PLATFORM_POSIX
#endif // VMIME_MESSAGING_SENDMAIL_SENDMAILTRANSPORT_HPP_INCLUDED

View File

@ -24,13 +24,13 @@
#include "vmime/types.hpp" #include "vmime/types.hpp"
#include "vmime/messaging/session.hpp" #include "vmime/messaging/session.hpp"
#include "vmime/messaging/authenticator.hpp" #include "vmime/messaging/authenticator.hpp"
#include "vmime/messaging/progressionListener.hpp"
#include "vmime/messaging/serviceFactory.hpp" #include "vmime/messaging/serviceFactory.hpp"
#include "vmime/messaging/serviceInfos.hpp" #include "vmime/messaging/serviceInfos.hpp"
#include "vmime/utility/progressionListener.hpp"
namespace vmime { namespace vmime {
namespace messaging { namespace messaging {

View File

@ -31,9 +31,10 @@
#include "vmime/messaging/serviceInfos.hpp" #include "vmime/messaging/serviceInfos.hpp"
#include "vmime/messaging/authenticator.hpp" #include "vmime/messaging/authenticator.hpp"
#include "vmime/messaging/progressionListener.hpp"
#include "vmime/messaging/timeoutHandler.hpp" #include "vmime/messaging/timeoutHandler.hpp"
#include "vmime/utility/progressionListener.hpp"
namespace vmime { namespace vmime {
namespace messaging { namespace messaging {

View File

@ -22,7 +22,7 @@
#include "vmime/messaging/authenticator.hpp" #include "vmime/messaging/authenticator.hpp"
#include "vmime/messaging/progressionListener.hpp"
#include "vmime/utility/url.hpp" #include "vmime/utility/url.hpp"
#include "vmime/propertySet.hpp" #include "vmime/propertySet.hpp"

View File

@ -54,7 +54,7 @@ public:
void noop(); void noop();
void send(const mailbox& expeditor, const mailboxList& recipients, utility::inputStream& is, const utility::stream::size_type size, progressionListener* progress = NULL); void send(const mailbox& expeditor, const mailboxList& recipients, utility::inputStream& is, const utility::stream::size_type size, utility::progressionListener* progress = NULL);
private: private:

View File

@ -51,7 +51,7 @@ public:
* @param msg message to send * @param msg message to send
* @param progress progression listener, or NULL if not used * @param progress progression listener, or NULL if not used
*/ */
virtual void send(vmime::message* msg, progressionListener* progress = NULL); virtual void send(vmime::message* msg, utility::progressionListener* progress = NULL);
/** Send a message over this transport service. /** Send a message over this transport service.
* *
@ -61,7 +61,7 @@ public:
* @param size size of the message data * @param size size of the message data
* @param progress progression listener, or NULL if not used * @param progress progression listener, or NULL if not used
*/ */
virtual void send(const mailbox& expeditor, const mailboxList& recipients, utility::inputStream& is, const utility::stream::size_type size, progressionListener* progress = NULL) = 0; virtual void send(const mailbox& expeditor, const mailboxList& recipients, utility::inputStream& is, const utility::stream::size_type size, utility::progressionListener* progress = NULL) = 0;
const Type getType() const; const Type getType() const;

View File

@ -0,0 +1,116 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED
#define VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED
#include "vmime/utility/stream.hpp"
namespace vmime {
namespace utility {
/** A stream whose input is filtered.
*/
class filteredInputStream : public inputStream
{
public:
/** Return a reference to the stream being filtered.
*
* @return stream being filtered
*/
virtual inputStream& getPreviousInputStream() = 0;
};
/** A stream whose output is filtered.
*/
class filteredOutputStream : public outputStream
{
public:
/** Return a reference to the stream being filtered.
*
* @return destination stream for filtered data
*/
virtual outputStream& getNextOutputStream() = 0;
};
/** A filtered output stream which replaces "\n."
* sequences with "\n.." sequences.
*/
class dotFilteredOutputStream : public filteredOutputStream
{
public:
/** Construct a new filter for the specified output stream.
*
* @param os stream into which write filtered data
*/
dotFilteredOutputStream(outputStream& os);
outputStream& getNextOutputStream();
void write(const value_type* const data, const size_type count);
private:
outputStream& m_stream;
value_type m_previousChar;
};
/** A filtered output stream which replaces CRLF sequences
* with single LF characters.
*/
class CRLFToLFFilteredOutputStream : public filteredOutputStream
{
public:
/** Construct a new filter for the specified output stream.
*
* @param os stream into which write filtered data
*/
CRLFToLFFilteredOutputStream(outputStream& os);
outputStream& getNextOutputStream();
void write(const value_type* const data, const size_type count);
private:
outputStream& m_stream;
value_type m_previousChar;
};
} // utility
} // vmime
#endif // VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED

View File

@ -17,12 +17,12 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// //
#ifndef VMIME_MESSAGING_PROGRESSIONLISTENER_HPP_INCLUDED #ifndef VMIME_UTILITY_PROGRESSIONLISTENER_HPP_INCLUDED
#define VMIME_MESSAGING_PROGRESSIONLISTENER_HPP_INCLUDED #define VMIME_UTILITY_PROGRESSIONLISTENER_HPP_INCLUDED
namespace vmime { namespace vmime {
namespace messaging { namespace utility {
/** An interface to implement if you want to be notified /** An interface to implement if you want to be notified
@ -39,8 +39,8 @@ public:
/** Allow the caller object to cancel the current operation. /** Allow the caller object to cancel the current operation.
* *
* @warning WARNING: this is implementation-dependant: the underlying * @warning WARNING: this is implementation-dependant: cancelling
* messaging protocol may not support this). * may not be supported by the notifier object.
* *
* @return true to cancel the operation, false otherwise * @return true to cancel the operation, false otherwise
*/ */
@ -49,7 +49,7 @@ public:
/** Called at the beginning of the operation. /** Called at the beginning of the operation.
* *
* @param predictedTotal predicted amount of units (this has * @param predictedTotal predicted amount of units (this has
* no concrete meaning: they are not bytes, nor percentage...) * no concrete meaning: these are not bytes, nor percentage...)
*/ */
virtual void start(const int predictedTotal) = 0; virtual void start(const int predictedTotal) = 0;
@ -68,8 +68,8 @@ public:
}; };
} // messaging } // utility
} // vmime } // vmime
#endif // VMIME_MESSAGING_PROGRESSIONLISTENER_HPP_INCLUDED #endif // VMIME_UTILITY_PROGRESSIONLISTENER_HPP_INCLUDED

View File

@ -25,8 +25,20 @@
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
#include "vmime/config.hpp"
#include "vmime/types.hpp" #include "vmime/types.hpp"
#include "vmime/utility/progressionListener.hpp"
#if VMIME_HAVE_MESSAGING_FEATURES
namespace vmime {
namespace messaging {
class socket; // forward reference
} // messaging
} // vmime
#endif
#if defined(_MSC_VER) && (_MSC_VER <= 1200) // VC++6 #if defined(_MSC_VER) && (_MSC_VER <= 1200) // VC++6
# include <cstring> # include <cstring>
#endif #endif
@ -160,6 +172,18 @@ outputStream& operator<<(outputStream& os, const T& t)
const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os); const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os);
/** Copy data from one stream into another stream using a buffered method
* and notify progression of the operation.
*
* @param is input stream (source data)
* @param os output stream (destination for data)
* @param length predicted number of bytes to copy
* @param progress listener to notify
* @return number of bytes copied
*/
const stream::size_type bufferedStreamCopy(inputStream& is, outputStream& os,
const stream::size_type length, progressionListener* progress);
// Adapters // Adapters
@ -296,6 +320,29 @@ private:
}; };
#if VMIME_HAVE_MESSAGING_FEATURES
/** An output stream that is connected to a socket.
*/
class outputStreamSocketAdapter : public outputStream
{
public:
outputStreamSocketAdapter(messaging::socket& sok);
void write(const value_type* const data, const size_type count);
private:
messaging::socket& m_socket;
};
#endif // VMIME_HAVE_MESSAGING_FEATURES
} // utility } // utility
} // vmime } // vmime

View File

@ -84,6 +84,7 @@
// Utilities // Utilities
#include "vmime/utility/datetimeUtils.hpp" #include "vmime/utility/datetimeUtils.hpp"
#include "vmime/utility/filteredStream.hpp"
// Messaging features // Messaging features
#if VMIME_HAVE_MESSAGING_FEATURES #if VMIME_HAVE_MESSAGING_FEATURES