Index: perl/lib/BarnOwl/Logging.pm
===================================================================
--- perl/lib/BarnOwl/Logging.pm	(revision eea7bed400b55cdc510b806ea4230d174b165470)
+++ perl/lib/BarnOwl/Logging.pm	(revision 5093c6f01fd51f20f4fe96ce622a09811e6eeaae)
@@ -15,4 +15,8 @@
 Modules wishing to customize how messages are logged should override the
 relevant subroutines in the appropriate subclass of L<BarnOwl::Message>.
+
+Modules wishing to log errors sending outgoing messages should call
+L<BarnOwl::Logging::log_outgoing_error> with the message that failed
+to be sent.
 
 =head2 EXPORTS
@@ -76,12 +80,68 @@
 }
 
-# For ease of use in C
-sub get_filenames_as_string {
-    my @rtn;
-    foreach my $filename (BarnOwl::Logging::get_filenames(@_)) {
-        $filename =~ s/\n/_/g;
-        push @rtn, $filename;
+=head2 should_log_message MESSAGE
+
+Determines whether or not the passed message should be logged.
+
+To customize the behavior of this method, override
+L<BarnOwl::Message::should_log>.
+
+=cut
+
+sub should_log_message {
+    my ($m) = @_;
+    # If there's a logfilter and this message matches it, log.
+    # pass quiet=1, because we don't care if the filter doesn't exist
+    return 1 if BarnOwl::message_matches_filter($m, BarnOwl::getvar('logfilter'), 1);
+    # otherwise we do things based on the logging variables
+    # skip login/logout messages if appropriate
+    return 0 if $m->is_loginout && BarnOwl::getvar('loglogins') eq 'off';
+    # check direction
+    return 0 if $m->is_outgoing && BarnOwl::getvar('loggingdirection') eq 'in';
+    return 0 if $m->is_incoming && BarnOwl::getvar('loggingdirection') eq 'out';
+    return $m->should_log;
+}
+
+=head2 log MESSAGE
+
+Call this method to (potentially) log a message.
+
+To customize the behavior of this method for your messages, override
+L<BarnOwl::Message::log>, L<BarnOwl::Message::should_log>,
+L<BarnOwl::Message::log_base_path>, and/or
+L<BarnOwl::Message::log_filenames>.
+
+=cut
+
+sub log {
+    my ($m) = @_;
+    return unless BarnOwl::Logging::should_log_message($m);
+    my $log_text = $m->log;
+    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
+        BarnOwl::Logging::enqueue_text($log_text, $filename);
     }
-    return join("\n", @rtn);
+}
+
+=head2 log_outgoing_error MESSAGE
+
+Call this method to (potentially) log an error in sending an
+outgoing message.  Errors get logged to the same file(s) as
+successful messages.
+
+To customize the behavior of this method for your messages, override
+L<BarnOwl::Message::log_outgoing_error>,
+L<BarnOwl::Message::should_log>,
+L<BarnOwl::Message::log_base_path>, and/or
+L<BarnOwl::Message::log_filenames>.
+
+=cut
+
+sub log_outgoing_error {
+    my ($m) = @_;
+    return unless BarnOwl::Logging::should_log_message($m);
+    my $log_text = $m->log_outgoing_error;
+    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
+        BarnOwl::Logging::enqueue_text($log_text, $filename);
+    }
 }
 
Index: perl/lib/BarnOwl/Message.pm
===================================================================
--- perl/lib/BarnOwl/Message.pm	(revision 9bfab40b6e10c70af6a97c0c1be89abbb557c3db)
+++ perl/lib/BarnOwl/Message.pm	(revision 5093c6f01fd51f20f4fe96ce622a09811e6eeaae)
@@ -225,4 +225,24 @@
     chomp $body;
     return "ERROR (BarnOwl): $recipient\n$body\n\n";
+}
+
+=head2 should_log MESSAGE
+
+Returns true if we should log C<MESSAGE>.  This does not override
+user settings; if the BarnOwl variable C<loggingdirection> is in,
+and C<MESSAGE> is outgoing and does not match the C<logfilter>, it
+will not get logged regardless of what this method returns.
+
+Note that this method I<does> override the BarnOwl C<logging>
+variable; if a derived class overrides this method and does not
+provide an alternative BarnOwl variable (such as C<classlogging>),
+the overriding method should check the BarnOwl C<logging> variable.
+
+Defaults to returning the value of the BarnOwl variable C<logging>.
+
+=cut
+
+sub should_log {
+    return BarnOwl::getvar('logging') eq 'on';
 }
 
Index: perl/lib/BarnOwl/Message/Zephyr.pm
===================================================================
--- perl/lib/BarnOwl/Message/Zephyr.pm	(revision eea7bed400b55cdc510b806ea4230d174b165470)
+++ perl/lib/BarnOwl/Message/Zephyr.pm	(revision 5093c6f01fd51f20f4fe96ce622a09811e6eeaae)
@@ -281,3 +281,12 @@
 }
 
+sub should_log {
+    my ($m) = @_;
+    if ($m->log_to_class_file) {
+        return BarnOwl::getvar('classlogging') eq 'on';
+    } else {
+        return BarnOwl::getvar('logging') eq 'on';
+    }
+}
+
 1;
