aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2005-04-28 10:57:41 +0000
committerVincent Richard <[email protected]>2005-04-28 10:57:41 +0000
commit38a86328282779dd8e94ad55e3c10687ebfbe979 (patch)
tree5a43264d9e380685750d4d6e9316fff940244651
parentFixed send example. (diff)
downloadvmime-38a86328282779dd8e94ad55e3c10687ebfbe979.tar.gz
vmime-38a86328282779dd8e94ad55e3c10687ebfbe979.zip
Sendmail implementation + filtered streams.
-rw-r--r--ChangeLog13
-rw-r--r--SConstruct101
-rw-r--r--src/exception.cpp12
-rw-r--r--src/messaging/builtinServices.inl5
-rw-r--r--src/messaging/imap/IMAPFolder.cpp6
-rw-r--r--src/messaging/imap/IMAPMessage.cpp13
-rw-r--r--src/messaging/maildir/maildirFolder.cpp9
-rw-r--r--src/messaging/maildir/maildirMessage.cpp6
-rw-r--r--src/messaging/pop3/POP3Folder.cpp6
-rw-r--r--src/messaging/pop3/POP3Message.cpp7
-rw-r--r--src/messaging/pop3/POP3Store.cpp6
-rw-r--r--src/messaging/sendmail/sendmailTransport.cpp387
-rw-r--r--src/messaging/smtp/SMTPTransport.cpp64
-rw-r--r--src/messaging/transport.cpp2
-rw-r--r--src/utility/filteredStream.cpp115
-rw-r--r--src/utility/stream.cpp43
-rw-r--r--vmime/exception.hpp15
-rw-r--r--vmime/messaging/folder.hpp10
-rw-r--r--vmime/messaging/imap/IMAPFolder.hpp6
-rw-r--r--vmime/messaging/imap/IMAPMessage.hpp6
-rw-r--r--vmime/messaging/imap/IMAPParser.hpp16
-rw-r--r--vmime/messaging/maildir/maildirFolder.hpp8
-rw-r--r--vmime/messaging/maildir/maildirMessage.hpp6
-rw-r--r--vmime/messaging/message.hpp7
-rw-r--r--vmime/messaging/pop3/POP3Folder.hpp6
-rw-r--r--vmime/messaging/pop3/POP3Message.hpp4
-rw-r--r--vmime/messaging/pop3/POP3Store.hpp4
-rw-r--r--vmime/messaging/sendmail/sendmailTransport.hpp98
-rw-r--r--vmime/messaging/service.hpp4
-rw-r--r--vmime/messaging/serviceFactory.hpp3
-rw-r--r--vmime/messaging/session.hpp2
-rw-r--r--vmime/messaging/smtp/SMTPTransport.hpp2
-rw-r--r--vmime/messaging/transport.hpp4
-rw-r--r--vmime/utility/filteredStream.hpp116
-rw-r--r--vmime/utility/progressionListener.hpp (renamed from vmime/messaging/progressionListener.hpp)16
-rw-r--r--vmime/utility/stream.hpp47
-rw-r--r--vmime/vmime.hpp1
37 files changed, 1025 insertions, 151 deletions
diff --git a/ChangeLog b/ChangeLog
index 19593b2c..53e4effb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,19 @@
VERSION 0.7.1cvs
================
+2005-04-27 Vincent Richard <[email protected]>
+
+ * 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 <[email protected]>
* defaultParameter.cpp: fixed a bug in implementation of RFC-2231 (values
diff --git a/SConstruct b/SConstruct
index 811bd828..b47344b3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -148,8 +148,10 @@ libvmime_sources = [
'vmime.hpp',
'utility/file.hpp',
'utility/datetimeUtils.cpp', 'utility/datetimeUtils.hpp',
+ 'utility/filteredStream.cpp', 'utility/filteredStream.hpp',
'utility/md5.cpp', 'utility/md5.hpp',
'utility/path.cpp', 'utility/path.hpp',
+ 'utility/progressionListener.hpp',
'utility/random.cpp', 'utility/random.hpp',
'utility/smartPtr.hpp',
'utility/stream.cpp', 'utility/stream.hpp',
@@ -185,7 +187,6 @@ libvmime_messaging_sources = [
'messaging/events.cpp', 'messaging/events.hpp',
'messaging/folder.cpp', 'messaging/folder.hpp',
'messaging/message.cpp', 'messaging/message.hpp',
- 'messaging/progressionListener.hpp',
'messaging/service.cpp', 'messaging/service.hpp',
'messaging/serviceFactory.cpp', 'messaging/serviceFactory.hpp',
'messaging/serviceInfos.hpp',
@@ -232,6 +233,12 @@ libvmime_messaging_proto_sources = [
'messaging/maildir/maildirMessage.cpp', 'messaging/maildir/maildirMessage.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
-# TODO
+defaultSendmailPath = WhereIs("sendmail")
+
+if defaultSendmailPath == None:
+ defaultSendmailPath = ''
+
# Command line options
opts = Options('options.cache')
@@ -453,8 +464,8 @@ opts.AddOptions(
'Specifies which protocols to build into the library.\n'
+ 'This option has no effect if "with_messaging" is not activated.\n'
+ 'Separate protocols with spaces; string must be quoted with ".\n'
- + 'Currently available protocols: pop3, smtp, imap, maildir.',
- '"pop3 smtp imap maildir"'
+ + 'Currently available protocols: pop3, smtp, imap, maildir, sendmail.',
+ '"pop3 smtp imap maildir sendmail"'
),
(
'with_platforms',
@@ -466,6 +477,11 @@ opts.AddOptions(
+ 'Currently available platform handlers: posix.',
'"posix"'
),
+ (
+ 'sendmail_path',
+ 'Specifies the path to sendmail.',
+ defaultSendmailPath
+ ),
EnumOption(
'with_wide_char_support',
'Support for wide characters (rarely used, should be set to "no")',
@@ -517,6 +533,7 @@ opts.AddOptions(
)
+
###############################
# Configuration Environment #
###############################
@@ -583,20 +600,6 @@ for platform in re.split('\W+', string.replace(env['with_platforms'], '"', '')):
if len(platform) >= 1:
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 0
+
# File-system support must be activated when 'maildir' protocol is selected
if env['with_messaging'] == 'yes':
if IsProtocolSupported(messaging_protocols, 'maildir'):
@@ -616,6 +620,48 @@ if env['with_messaging'] == 'yes':
print "ERROR: 'maildir' protocol requires file-system support!\n"
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 #
@@ -724,6 +770,12 @@ for platform in libvmime_platforms_sources:
if not platform in platforms:
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("""
#endif // VMIME_CONFIG_HPP_INCLUDED
@@ -1433,6 +1485,13 @@ esac
#
+# System mail
+#
+
+AC_PATH_PROG(SENDMAIL, sendmail, /usr/sbin/sendmail, /usr/sbin:/usr/lib)
+
+
+#
# Detect some platform-specific stuff
#
@@ -1629,6 +1688,10 @@ typedef unsigned ${VMIME_TYPE_INT32} vmime_uint32;
configure_in.write("""
" > 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
echo "// Additional defines" >> vmime/config.hpp
@@ -1926,7 +1989,7 @@ typedef unsigned int vmime_uint32;
// -- Messaging support
#define VMIME_HAVE_MESSAGING_FEATURES 1
// -- 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_SMTP 1
#define VMIME_BUILTIN_MESSAGING_PROTO_IMAP 1
diff --git a/src/exception.cpp b/src/exception.cpp
index b7be006c..bac5c728 100644
--- a/src/exception.cpp
+++ b/src/exception.cpp
@@ -294,6 +294,18 @@ exception* invalid_argument::clone() const { return new invalid_argument(*this);
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
diff --git a/src/messaging/builtinServices.inl b/src/messaging/builtinServices.inl
index cea2f7a8..d1b63a30 100644
--- a/src/messaging/builtinServices.inl
+++ b/src/messaging/builtinServices.inl
@@ -47,5 +47,10 @@
REGISTER_SERVICE(maildir::maildirStore, maildir);
#endif
+#if VMIME_BUILTIN_MESSAGING_PROTO_SENDMAIL
+ #include "vmime/messaging/sendmail/sendmailTransport.hpp"
+ REGISTER_SERVICE(sendmail::sendmailTransport, sendmail);
+#endif
+
#endif // VMIME_BUILDING_DOC
diff --git a/src/messaging/imap/IMAPFolder.cpp b/src/messaging/imap/IMAPFolder.cpp
index 5bbfa148..39404c82 100644
--- a/src/messaging/imap/IMAPFolder.cpp
+++ b/src/messaging/imap/IMAPFolder.cpp
@@ -596,7 +596,7 @@ std::vector <folder*> IMAPFolder::getFolders(const bool recursive)
void IMAPFolder::fetchMessages(std::vector <message*>& msg, const int options,
- progressionListener* progress)
+ utility::progressionListener* progress)
{
if (!m_store)
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,
- vmime::datetime* date, progressionListener* progress)
+ vmime::datetime* date, utility::progressionListener* progress)
{
std::ostringstream 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,
- vmime::datetime* date, progressionListener* progress)
+ vmime::datetime* date, utility::progressionListener* progress)
{
if (!m_store)
throw exceptions::illegal_state("Store disconnected");
diff --git a/src/messaging/imap/IMAPMessage.cpp b/src/messaging/imap/IMAPMessage.cpp
index 629668c5..a2220c68 100644
--- a/src/messaging/imap/IMAPMessage.cpp
+++ b/src/messaging/imap/IMAPMessage.cpp
@@ -243,7 +243,7 @@ class IMAPMessage_literalHandler : public IMAPParser::literalHandler
{
public:
- IMAPMessage_literalHandler(utility::outputStream& os, progressionListener* progress)
+ IMAPMessage_literalHandler(utility::outputStream& os, utility::progressionListener* progress)
: m_os(os), m_progress(progress)
{
}
@@ -268,7 +268,7 @@ public:
private:
utility::outputStream& m_os;
- progressionListener* m_progress;
+ utility::progressionListener* m_progress;
};
#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
{
if (!m_folder)
@@ -377,7 +377,7 @@ void IMAPMessage::extract(utility::outputStream& os, progressionListener* progre
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
{
if (!m_folder)
@@ -401,8 +401,9 @@ void IMAPMessage::fetchPartHeader(part& p)
}
-void IMAPMessage::extract(const part* p, utility::outputStream& os, progressionListener* progress,
- const int start, const int length, const bool headerOnly) const
+void IMAPMessage::extract(const part* p, utility::outputStream& os,
+ utility::progressionListener* progress, const int start,
+ const int length, const bool headerOnly) const
{
IMAPMessage_literalHandler literalHandler(os, progress);
diff --git a/src/messaging/maildir/maildirFolder.cpp b/src/messaging/maildir/maildirFolder.cpp
index c3b7e71c..fa337d09 100644
--- a/src/messaging/maildir/maildirFolder.cpp
+++ b/src/messaging/maildir/maildirFolder.cpp
@@ -839,7 +839,7 @@ void maildirFolder::setMessageFlagsImpl
void maildirFolder::addMessage(vmime::message* msg, const int flags,
- vmime::datetime* date, progressionListener* progress)
+ vmime::datetime* date, utility::progressionListener* progress)
{
std::ostringstream 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,
- const int flags, vmime::datetime* /* date */, progressionListener* progress)
+ const int flags, vmime::datetime* /* date */, utility::progressionListener* progress)
{
if (!m_store)
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,
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();
@@ -1295,7 +1296,7 @@ store* maildirFolder::getStore()
void maildirFolder::fetchMessages(std::vector <message*>& msg,
- const int options, progressionListener* progress)
+ const int options, utility::progressionListener* progress)
{
if (!m_store)
throw exceptions::illegal_state("Store disconnected");
diff --git a/src/messaging/maildir/maildirMessage.cpp b/src/messaging/maildir/maildirMessage.cpp
index 9b728359..2815e980 100644
--- a/src/messaging/maildir/maildirMessage.cpp
+++ b/src/messaging/maildir/maildirMessage.cpp
@@ -309,14 +309,14 @@ void maildirMessage::setFlags(const int flags, const int mode)
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);
}
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);
@@ -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
{
utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory();
diff --git a/src/messaging/pop3/POP3Folder.cpp b/src/messaging/pop3/POP3Folder.cpp
index c70e2b5b..6f4cb237 100644
--- a/src/messaging/pop3/POP3Folder.cpp
+++ b/src/messaging/pop3/POP3Folder.cpp
@@ -293,7 +293,7 @@ std::vector <folder*> POP3Folder::getFolders(const bool /* recursive */)
void POP3Folder::fetchMessages(std::vector <message*>& msg, const int options,
- progressionListener* progress)
+ utility::progressionListener* progress)
{
if (!m_store)
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 */,
- vmime::datetime* /* date */, progressionListener* /* progress */)
+ vmime::datetime* /* date */, utility::progressionListener* /* progress */)
{
throw exceptions::operation_not_supported();
}
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();
}
diff --git a/src/messaging/pop3/POP3Message.cpp b/src/messaging/pop3/POP3Message.cpp
index 01680d34..46d57ba9 100644
--- a/src/messaging/pop3/POP3Message.cpp
+++ b/src/messaging/pop3/POP3Message.cpp
@@ -110,8 +110,8 @@ const header& POP3Message::getHeader() const
}
-void POP3Message::extract(utility::outputStream& os, progressionListener* progress,
- const int start, const int length) const
+void POP3Message::extract(utility::outputStream& os,
+ utility::progressionListener* progress, const int start, const int length) const
{
if (!m_folder)
throw exceptions::illegal_state("Folder closed");
@@ -146,7 +146,8 @@ void POP3Message::extract(utility::outputStream& os, progressionListener* progre
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
{
throw exceptions::operation_not_supported();
diff --git a/src/messaging/pop3/POP3Store.cpp b/src/messaging/pop3/POP3Store.cpp
index d6ece2a0..69e09bc6 100644
--- a/src/messaging/pop3/POP3Store.cpp
+++ b/src/messaging/pop3/POP3Store.cpp
@@ -311,7 +311,7 @@ void POP3Store::sendRequest(const string& buffer, const bool end)
void POP3Store::readResponse(string& buffer, const bool multiLine,
- progressionListener* progress)
+ utility::progressionListener* progress)
{
bool foundTerminator = false;
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,
- const int predictedSize)
+void POP3Store::readResponse(utility::outputStream& os,
+ utility::progressionListener* progress, const int predictedSize)
{
bool foundTerminator = false;
int current = 0, total = predictedSize;
diff --git a/src/messaging/sendmail/sendmailTransport.cpp b/src/messaging/sendmail/sendmailTransport.cpp
new file mode 100644
index 00000000..87d1637f
--- /dev/null
+++ b/src/messaging/sendmail/sendmailTransport.cpp
@@ -0,0 +1,387 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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 <[email protected]>
+// 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
diff --git a/src/messaging/smtp/SMTPTransport.cpp b/src/messaging/smtp/SMTPTransport.cpp
index 16fc1454..4f7df174 100644
--- a/src/messaging/smtp/SMTPTransport.cpp
+++ b/src/messaging/smtp/SMTPTransport.cpp
@@ -26,6 +26,8 @@
#include "vmime/messaging/authHelper.hpp"
+#include "vmime/utility/filteredStream.hpp"
+
namespace vmime {
namespace messaging {
@@ -259,7 +261,7 @@ void SMTPTransport::noop()
void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients,
utility::inputStream& is, const utility::stream::size_type size,
- progressionListener* progress)
+ utility::progressionListener* progress)
{
// If no recipient/expeditor was found, throw an exception
if (recipients.isEmpty())
@@ -304,63 +306,13 @@ void SMTPTransport::send(const mailbox& expeditor, const mailboxList& recipients
throw exceptions::command_error("DATA", response);
}
- int current = 0, total = size;
-
- if (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);
- }
- }
+ // Stream copy with "\n." to "\n.." transformation
+ utility::outputStreamSocketAdapter sos(*m_socket);
+ utility::dotFilteredOutputStream fos(sos);
- if (progress)
- progress->stop(total);
+ utility::bufferedStreamCopy(is, fos, size, progress);
+ // Send end-of-data delimiter
m_socket->sendRaw("\r\n.\r\n", 5);
readResponse(response);
diff --git a/src/messaging/transport.cpp b/src/messaging/transport.cpp
index 1caa7fae..0b52aa39 100644
--- a/src/messaging/transport.cpp
+++ b/src/messaging/transport.cpp
@@ -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
mailbox expeditor;
diff --git a/src/utility/filteredStream.cpp b/src/utility/filteredStream.cpp
new file mode 100644
index 00000000..9586f165
--- /dev/null
+++ b/src/utility/filteredStream.cpp
@@ -0,0 +1,115 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/utility/stream.cpp b/src/utility/stream.cpp
index 397bf20b..3899eb52 100644
--- a/src/utility/stream.cpp
+++ b/src/utility/stream.cpp
@@ -23,6 +23,10 @@
#include <algorithm> // for std::copy
#include <iterator> // for std::back_inserter
+#if VMIME_HAVE_MESSAGING_FEATURES
+ #include "vmime/messaging/socket.hpp"
+#endif
+
namespace vmime {
namespace utility {
@@ -46,9 +50,19 @@ outputStream& operator<<(outputStream& os, const string& str)
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::size_type total = 0;
+ if (progress != NULL)
+ progress->start(length);
+
while (!is.eof())
{
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);
total += read;
+
+ if (progress != NULL)
+ progress->progress(total, std::max(total, length));
}
}
+ if (progress != NULL)
+ progress->stop(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
} // vmime
diff --git a/vmime/exception.hpp b/vmime/exception.hpp
index 85f0a3ff..396ae5b3 100644
--- a/vmime/exception.hpp
+++ b/vmime/exception.hpp
@@ -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
diff --git a/vmime/messaging/folder.hpp b/vmime/messaging/folder.hpp
index 9a8a1155..610e55af 100644
--- a/vmime/messaging/folder.hpp
+++ b/vmime/messaging/folder.hpp
@@ -25,11 +25,13 @@
#include "vmime/types.hpp"
#include "vmime/dateTime.hpp"
-#include "vmime/messaging/progressionListener.hpp"
+
#include "vmime/messaging/message.hpp"
#include "vmime/messaging/events.hpp"
+
#include "vmime/utility/path.hpp"
#include "vmime/utility/stream.hpp"
+#include "vmime/utility/progressionListener.hpp"
namespace vmime {
@@ -244,7 +246,7 @@ public:
* @param date date/time for the new message (if NULL, the current time is 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.
*
@@ -254,7 +256,7 @@ public:
* @param date date/time for the new message (if NULL, the current time is 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.
*
@@ -328,7 +330,7 @@ public:
* @param options objects to fetch (combination of folder::FetchOptions flags)
* @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.
*
diff --git a/vmime/messaging/imap/IMAPFolder.hpp b/vmime/messaging/imap/IMAPFolder.hpp
index 4df20e44..128fea3c 100644
--- a/vmime/messaging/imap/IMAPFolder.hpp
+++ b/vmime/messaging/imap/IMAPFolder.hpp
@@ -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 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(utility::inputStream& is, const int size, 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, utility::progressionListener* progress = NULL);
void copyMessage(const folder::path& dest, const int num);
void copyMessages(const folder::path& dest, const int from = 1, const int to = -1);
@@ -108,7 +108,7 @@ public:
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);
const int getFetchCapabilities() const;
diff --git a/vmime/messaging/imap/IMAPMessage.hpp b/vmime/messaging/imap/IMAPMessage.hpp
index b3c10562..f9c22a75 100644
--- a/vmime/messaging/imap/IMAPMessage.hpp
+++ b/vmime/messaging/imap/IMAPMessage.hpp
@@ -64,8 +64,8 @@ public:
const int getFlags() const;
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 extractPart(const part& p, 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, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void fetchPartHeader(part& p);
@@ -75,7 +75,7 @@ private:
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);
diff --git a/vmime/messaging/imap/IMAPParser.hpp b/vmime/messaging/imap/IMAPParser.hpp
index 4a4c8f59..368215b0 100644
--- a/vmime/messaging/imap/IMAPParser.hpp
+++ b/vmime/messaging/imap/IMAPParser.hpp
@@ -28,13 +28,13 @@
#include "vmime/utility/smartPtr.hpp"
#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/progressionListener.hpp"
#include "vmime/encoderB64.hpp"
#include "vmime/encoderQP.hpp"
#include "vmime/platformDependant.hpp"
-#include "vmime/messaging/progressionListener.hpp"
#include "vmime/messaging/timeoutHandler.hpp"
#include "vmime/messaging/socket.hpp"
@@ -135,7 +135,7 @@ public:
{
protected:
- target(class progressionListener* progress) : m_progress(progress) {}
+ target(utility::progressionListener* progress) : m_progress(progress) {}
target(const target&) {}
public:
@@ -143,13 +143,13 @@ public:
virtual ~target() { }
- class progressionListener* progressionListener() { return (m_progress); }
+ utility::progressionListener* progressionListener() { return (m_progress); }
virtual void putData(const string& chunk) = 0;
private:
- class progressionListener* m_progress;
+ utility::progressionListener* m_progress;
};
@@ -158,7 +158,7 @@ public:
{
public:
- targetString(class progressionListener* progress, vmime::string& str)
+ targetString(utility::progressionListener* progress, vmime::string& str)
: target(progress), m_string(str) { }
const vmime::string& string() const { return (m_string); }
@@ -181,7 +181,7 @@ public:
{
public:
- targetStream(class progressionListener* progress, utility::outputStream& stream)
+ targetStream(utility::progressionListener* progress, utility::outputStream& stream)
: target(progress), m_stream(stream) { }
const utility::outputStream& stream() const { return (m_stream); }
@@ -809,7 +809,7 @@ public:
m_value = "[literal-handler]";
const string::size_type length = text->value().length();
- progressionListener* progress = target->progressionListener();
+ utility::progressionListener* progress = target->progressionListener();
if (progress)
{
@@ -4914,7 +4914,7 @@ private:
IMAPTag* m_tag;
socket* m_socket;
- progressionListener* m_progress;
+ utility::progressionListener* m_progress;
literalHandler* m_literalHandler;
diff --git a/vmime/messaging/maildir/maildirFolder.hpp b/vmime/messaging/maildir/maildirFolder.hpp
index 0b880f15..8eaaf333 100644
--- a/vmime/messaging/maildir/maildirFolder.hpp
+++ b/vmime/messaging/maildir/maildirFolder.hpp
@@ -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 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(utility::inputStream& is, const int size, 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, utility::progressionListener* progress = NULL);
void copyMessage(const folder::path& dest, const int num);
void copyMessages(const folder::path& dest, const int from = 1, const int to = -1);
@@ -108,7 +108,7 @@ public:
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);
const int getFetchCapabilities() const;
@@ -132,7 +132,7 @@ private:
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 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);
diff --git a/vmime/messaging/maildir/maildirMessage.hpp b/vmime/messaging/maildir/maildirMessage.hpp
index ffbc1ca2..cd345784 100644
--- a/vmime/messaging/maildir/maildirMessage.hpp
+++ b/vmime/messaging/maildir/maildirMessage.hpp
@@ -65,8 +65,8 @@ public:
const int getFlags() const;
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 extractPart(const part& p, 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, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void fetchPartHeader(part& p);
@@ -78,7 +78,7 @@ private:
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;
diff --git a/vmime/messaging/message.hpp b/vmime/messaging/message.hpp
index ee32c753..47cc6b76 100644
--- a/vmime/messaging/message.hpp
+++ b/vmime/messaging/message.hpp
@@ -22,7 +22,8 @@
#include "vmime/header.hpp"
-#include "vmime/messaging/progressionListener.hpp"
+
+#include "vmime/utility/progressionListener.hpp"
#include "vmime/utility/stream.hpp"
@@ -257,7 +258,7 @@ public:
* @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).
*
@@ -269,7 +270,7 @@ public:
* @param start index of the first byte 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.
*
diff --git a/vmime/messaging/pop3/POP3Folder.hpp b/vmime/messaging/pop3/POP3Folder.hpp
index 3cf9855d..8cfe12db 100644
--- a/vmime/messaging/pop3/POP3Folder.hpp
+++ b/vmime/messaging/pop3/POP3Folder.hpp
@@ -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 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(utility::inputStream& is, const int size, 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, utility::progressionListener* progress = NULL);
void copyMessage(const folder::path& dest, const int num);
void copyMessages(const folder::path& dest, const int from = 1, const int to = -1);
@@ -107,7 +107,7 @@ public:
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);
const int getFetchCapabilities() const;
diff --git a/vmime/messaging/pop3/POP3Message.hpp b/vmime/messaging/pop3/POP3Message.hpp
index 82b5b132..c19d7579 100644
--- a/vmime/messaging/pop3/POP3Message.hpp
+++ b/vmime/messaging/pop3/POP3Message.hpp
@@ -64,8 +64,8 @@ public:
const int getFlags() const;
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 extractPart(const part& p, 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, utility::progressionListener* progress = NULL, const int start = 0, const int length = -1) const;
void fetchPartHeader(part& p);
diff --git a/vmime/messaging/pop3/POP3Store.hpp b/vmime/messaging/pop3/POP3Store.hpp
index 598025ca..c7528f9c 100644
--- a/vmime/messaging/pop3/POP3Store.hpp
+++ b/vmime/messaging/pop3/POP3Store.hpp
@@ -74,8 +74,8 @@ private:
static void stripResponseCode(const string& buffer, string& result);
void sendRequest(const string& buffer, const bool end = true);
- void readResponse(string& buffer, const bool multiLine, progressionListener* progress = NULL);
- void readResponse(utility::outputStream& os, progressionListener* progress = NULL, const int predictedSize = 0);
+ void readResponse(string& buffer, const bool multiLine, utility::progressionListener* progress = NULL);
+ 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 checkOneTerminator(string& buffer, const string& term);
diff --git a/vmime/messaging/sendmail/sendmailTransport.hpp b/vmime/messaging/sendmail/sendmailTransport.hpp
new file mode 100644
index 00000000..e3ee78c5
--- /dev/null
+++ b/vmime/messaging/sendmail/sendmailTransport.hpp
@@ -0,0 +1,98 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
diff --git a/vmime/messaging/service.hpp b/vmime/messaging/service.hpp
index 212e2c55..cf12e213 100644
--- a/vmime/messaging/service.hpp
+++ b/vmime/messaging/service.hpp
@@ -24,13 +24,13 @@
#include "vmime/types.hpp"
#include "vmime/messaging/session.hpp"
-
#include "vmime/messaging/authenticator.hpp"
-#include "vmime/messaging/progressionListener.hpp"
#include "vmime/messaging/serviceFactory.hpp"
#include "vmime/messaging/serviceInfos.hpp"
+#include "vmime/utility/progressionListener.hpp"
+
namespace vmime {
namespace messaging {
diff --git a/vmime/messaging/serviceFactory.hpp b/vmime/messaging/serviceFactory.hpp
index 5c17afcc..782e4c75 100644
--- a/vmime/messaging/serviceFactory.hpp
+++ b/vmime/messaging/serviceFactory.hpp
@@ -31,9 +31,10 @@
#include "vmime/messaging/serviceInfos.hpp"
#include "vmime/messaging/authenticator.hpp"
-#include "vmime/messaging/progressionListener.hpp"
#include "vmime/messaging/timeoutHandler.hpp"
+#include "vmime/utility/progressionListener.hpp"
+
namespace vmime {
namespace messaging {
diff --git a/vmime/messaging/session.hpp b/vmime/messaging/session.hpp
index 958ee448..bce4a2c0 100644
--- a/vmime/messaging/session.hpp
+++ b/vmime/messaging/session.hpp
@@ -22,7 +22,7 @@
#include "vmime/messaging/authenticator.hpp"
-#include "vmime/messaging/progressionListener.hpp"
+
#include "vmime/utility/url.hpp"
#include "vmime/propertySet.hpp"
diff --git a/vmime/messaging/smtp/SMTPTransport.hpp b/vmime/messaging/smtp/SMTPTransport.hpp
index 9b2eaa9b..3ccfdd49 100644
--- a/vmime/messaging/smtp/SMTPTransport.hpp
+++ b/vmime/messaging/smtp/SMTPTransport.hpp
@@ -54,7 +54,7 @@ public:
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:
diff --git a/vmime/messaging/transport.hpp b/vmime/messaging/transport.hpp
index 8ffe8ad2..272fdb32 100644
--- a/vmime/messaging/transport.hpp
+++ b/vmime/messaging/transport.hpp
@@ -51,7 +51,7 @@ public:
* @param msg message to send
* @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.
*
@@ -61,7 +61,7 @@ public:
* @param size size of the message data
* @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;
diff --git a/vmime/utility/filteredStream.hpp b/vmime/utility/filteredStream.hpp
new file mode 100644
index 00000000..fc014e4e
--- /dev/null
+++ b/vmime/utility/filteredStream.hpp
@@ -0,0 +1,116 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/messaging/progressionListener.hpp b/vmime/utility/progressionListener.hpp
index a1008d16..24c2f35c 100644
--- a/vmime/messaging/progressionListener.hpp
+++ b/vmime/utility/progressionListener.hpp
@@ -17,12 +17,12 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
-#ifndef VMIME_MESSAGING_PROGRESSIONLISTENER_HPP_INCLUDED
-#define VMIME_MESSAGING_PROGRESSIONLISTENER_HPP_INCLUDED
+#ifndef VMIME_UTILITY_PROGRESSIONLISTENER_HPP_INCLUDED
+#define VMIME_UTILITY_PROGRESSIONLISTENER_HPP_INCLUDED
namespace vmime {
-namespace messaging {
+namespace utility {
/** An interface to implement if you want to be notified
@@ -39,8 +39,8 @@ public:
/** Allow the caller object to cancel the current operation.
*
- * @warning WARNING: this is implementation-dependant: the underlying
- * messaging protocol may not support this).
+ * @warning WARNING: this is implementation-dependant: cancelling
+ * may not be supported by the notifier object.
*
* @return true to cancel the operation, false otherwise
*/
@@ -49,7 +49,7 @@ public:
/** Called at the beginning of the operation.
*
* @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;
@@ -68,8 +68,8 @@ public:
};
-} // messaging
+} // utility
} // vmime
-#endif // VMIME_MESSAGING_PROGRESSIONLISTENER_HPP_INCLUDED
+#endif // VMIME_UTILITY_PROGRESSIONLISTENER_HPP_INCLUDED
diff --git a/vmime/utility/stream.hpp b/vmime/utility/stream.hpp
index 91f3f573..c9967496 100644
--- a/vmime/utility/stream.hpp
+++ b/vmime/utility/stream.hpp
@@ -25,8 +25,20 @@
#include <ostream>
#include <sstream>
+#include "vmime/config.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
# include <cstring>
#endif
@@ -160,6 +172,18 @@ outputStream& operator<<(outputStream& os, const T& t)
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
@@ -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
} // vmime
diff --git a/vmime/vmime.hpp b/vmime/vmime.hpp
index c0e52d3b..b5cac466 100644
--- a/vmime/vmime.hpp
+++ b/vmime/vmime.hpp
@@ -84,6 +84,7 @@
// Utilities
#include "vmime/utility/datetimeUtils.hpp"
+#include "vmime/utility/filteredStream.hpp"
// Messaging features
#if VMIME_HAVE_MESSAGING_FEATURES