# See bottom of file for license and copyright information
package Foswiki::Configure::Wizards::SendTestEmail;

=begin TML

---++ package Foswiki::Configure::Wizards::SendTestEmail

Wizard to test email.

=cut

use strict;
use warnings;

use Foswiki::Configure::Wizard ();
our @ISA = ('Foswiki::Configure::Wizard');

# Use to disable stream redirection during $net->sendEmail. This is
# required because Foswiki::Net doesn't use the Foswiki::Sandbox :-(
our $noredirect = 0;

# WIZARD
sub send {
    my ( $this, $reporter ) = @_;

    unless ( $Foswiki::cfg{EnableEmail} ) {
        $reporter->ERROR("Cannot send mail - {EnableEmail} is false");
        return;
    }

    # A non-null value is required for this to make sense
    unless ( $Foswiki::cfg{WebMasterEmail} ) {
        $reporter->ERROR("Cannot send mail - {WebMasterEmail} is blank");
        return;
    }

    # Expand a couple of required config settings for
    # Foswiki::Net::sendEmail after making sure we can restore them.
    Foswiki::Configure::Load::expandValue(
        $Foswiki::cfg{Email}{SmimeCertificateFile} );

    Foswiki::Configure::Load::expandValue( $Foswiki::cfg{Email}{SmimeKeyFile} );

    if ( $Foswiki::cfg{Engine} && $Foswiki::cfg{Engine} =~ m/FastCGI/ ) {
        $noredirect = 1;    # FCGI doesn't allow redirection of STDERR
    }

    eval { _sendTestEmail($reporter); };
    die $@ if $@;
    return;                 # return the report
}

# Send a test email to the address in the value
sub _sendTestEmail {
    my $reporter = shift;

    my $fromName = $Foswiki::cfg{Email}{WikiAgentName}
      || $Foswiki::cfg{WebMasterName};
    my $fromAddr = $Foswiki::cfg{Email}{WikiAgentEmail}
      || $Foswiki::cfg{WebMasterEmail};

    require Foswiki::Net;

    my $neterrors = '';
    my $stderr    = '';
    my $stdout    = '';

    {
        local $Foswiki::cfg{SMTP}{Debug} = 1;

        my $smimeHTMLText = << "NOTSMIME";

<p>You have not configured <b>Foswiki</b> to send S/MIME signed e-mail notifications.

<p>To assure your users of the authenticity of mail from <b>Foswiki</b>,
which often contains hyperlinks, you may wish to consider enabling
this feature.
NOTSMIME

        if ( $Foswiki::cfg{Email}{EnableSMIME} ) {
            my $smimeCert = '';
            if ( $Foswiki::cfg{Email}{SmimeCertificateFile} ) {
                $smimeCert =
"using the certificate in =$Foswiki::cfg{Email}{SmimeCertificateFile}=.";
            }
            else {
                $smimeCert =
"using a Foswiki self-signed or Foswiki-requested certificate.";
            }
            $smimeHTMLText = << "SMIME";
<p>You have configured <b>Foswiki</b> to send S/MIME signed e-mail notifications
$smimeCert

<p>This message should be signed with the certificate that you
selected.  Mail clients vary in how they present this; typically
they use a certificate or padlock icon.

<p>If this message is not signed or if the signature is invalid, check
the ={Email}{SmimeCertificateFile}=, ={Email}{SmimeKeyFile}=
and ={Email}{SmimeKeyPassword}= settings, as well as the system logs.
SMIME
        }

        my $smimePlainText = $smimeHTMLText;
        $smimePlainText =~ s/<[^>]*>//g;

        my $msg = << "MAILTEST";
From: "$fromName" <$fromAddr>
To: "$Foswiki::cfg{WebMasterName}" <$Foswiki::cfg{WebMasterEmail}>
Subject: Test of Foswiki e-mail to $Foswiki::cfg{WebMasterName} 
Auto-Submitted: auto-generated
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="=_=0i0k0i0w0s0o0fXuOi0E0A"
Content-ID: <parta.08030205.07080409\@foswiki.org>

This is a multi-part message in MIME format.

--=_=0i0k0i0w0s0o0fXuOi0E0A
Content-Type: text/plain; charset=iso-8859-1; format=flowed
Content-Transfer-Encoding: 8bit

This is a test e-mail from Foswiki.  It is a slightly-modified copy
of an actual notification e-mail generated by the Foswiki topic change
notification system.  It is delivered in both plain text (what you
are viewing now) and HTML versions.  Your e-mail client determines
which version you view.
$smimePlainText
Successfully receiving and viewing this message indicates that
the destination e-mail address is active, and that the content
generated by Foswiki is not disturbed by any e-mail filters or
mail transport system barriers that may be present.

The sample notification follows. (Note that although the hyperlinks
in the message are active, the topic mentioned does not exist.):

--------------------------------------------------------------

This is an automated e-mail from Foswiki.

New or changed topics in Foswiki.Development, since 04 Nov 2012 - 12:40:

- SampleTopicName (SampleUser, 04 Nov 2012 - 23:16) r31->r32
http://foswiki.org/Development/ASampleTopic


Review recent changes in:
  http://foswiki.org/Development/WebChanges

Subscribe / Unsubscribe in:
  http://foswiki.org/Development/WebNotify

--=_=0i0k0i0w0s0o0fXuOi0E0A
Content-Type: multipart/related;
 boundary="------------010706080204060506050309"


--------------010706080204060506050309
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Content-ID: <partb.08030205.07080409\@foswiki.org>

<img src="cid:part1.08030205.07080409\@foswiki.org" alt="Powered by
      Foswiki, The Free and Open Source Wiki" style="border:none;"
      border="0"><br>
<h2>This is a test e-mail from Foswiki.</h2>  It is a slightly-modified copy
of an actual notification e-mail generated by the <b>Foswiki</b> topic change
notification system.  It is delivered in both HTML (what you
are viewing now) and plain text versions.  Your e-mail client determines
which version you view.
$smimeHTMLText
<p>Successfully receiving and viewing this message indicates that
the destination e-mail address is active, and that the content
generated by <b>Foswiki</b> is not disturbed by any e-mail filters or
mail transport system barriers that may be present.
<p>The sample notification follows. (Note that although the hyperlinks
in the message are active, the topic mentioned does not exist.):
<hr>
<h2>This is an automated e-mail from Foswiki.</h2>
<p>
<em>New or changed topics in Foswiki.Development, since 04 Nov 2012 - 12:40:</em>
</p>
<table width="100%" border="0" cellpadding="0" cellspacing="4">
<tr bgcolor="#B9DAFF">
  <td width="50%">
    <b>Topics in Development web:</b>
  </td><td width="30%">
    <b>Changed:</b> (now 00:15)
  </td><td width="20%">
    <b>Changed by:</b>
  </td>
</tr>
<tr>
  <td width="50%">
    <a href="http://foswiki.org/Development/ASampleTopic"><b>ASampleTopic</b></a>
  </td><td width="30%">
    <a href="http://foswiki.org/bin/rdiff/Development/ASampleTopic?rev2=31&amp;rev1=32" rel='nofollow'>04 Nov 2012 - 23:16</a> - r31-&gt;r32
  </td><td width="20%">
    <a href="http://foswiki.org/Main/SampleUser">Sample Wiki User</a>
  </td>
</tr>
<tr>
  <td colspan="2">
    <font size="-1">
     This would include a few lines from the topic that changed.<br /><ins>   This indicates text that was added.</ins><br /><del>And this text was deleted</del>

<br />   Main.SampleUser   04 Nov 2012 </font>
  </td><td width="20%">
    &nbsp;
  </td>
</tr></table>
<br clear="all" />
<p>Review recent changes in:
  <a href="http://foswiki.org/Development/WebChanges">http://foswiki.org/Development/WebChanges</a> </p>

<p>Subscribe / Unsubscribe in:
  <a href="http://foswiki.org/Development/WebNotify">http://foswiki.org/Development/WebNotify</a> </p>


--------------010706080204060506050309
Content-Type: image/png;
 name="foswiki-logo.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.08030205.07080409\@foswiki.org>
Content-Disposition: inline;
 filename="foswiki-logo.png"

[encoded data, 5183 characters]
U4kyGRD1h/t/K/8VYAAe30lsvO6PVgAAAABJRU5ErkJggg==
--------------010706080204060506050309--

--=_=0i0k0i0w0s0o0fXuOi0E0A--
MAILTEST

        my $net = Foswiki::Net->new();

        # Redirect streams so we can capture errors from the sendmail
        # program (which does not use Foswiki::Sandbox)
        my ( $savedOut, $savedErr );

        die "Can't save STDERR: $!"
          unless ($noredirect) || open( $savedErr, '>&STDERR' );

        die "Can't close original STDERR: $!"
          unless ($noredirect) || close(STDERR);

        eval {
            # STDERR has been closed
            die "Can't capture STDERR: $!"
              unless ($noredirect) || open( STDERR, '+>', undef );

            local $/ = undef;
            eval {
                # STDERR has been captured
                die "Can't save STDOUT: $!"
                  unless ($noredirect) || open( $savedOut, '>&STDOUT' );

                die "Can't close original STDOUT: $!"
                  unless ($noredirect) || close(STDOUT);

                eval {
                    # STDOUT has been closed
                    die "Can't capture STDOUT: $!"
                      unless ($noredirect) || open( STDOUT, '+>', undef );
                    eval {
                        eval { $neterrors .= $net->sendEmail( $msg, 1 ); };
                        print $savedErr($@) if $@;
                        $neterrors .= $@ if $@;

                        die "Seek: STDOUT: $!"
                          unless ($noredirect) || seek( STDOUT, 0, 0 );

                        $stdout = <STDOUT>;
                    };
                    die( ( $@ || '' ) . " Can't close capturing STDOUT: $!" )
                      unless ($noredirect) || close(STDOUT);
                };

                die( ( $@ || '' ) . " Can't restore STDOUT: $!" )
                  unless ($noredirect) || open( STDOUT, '>&', $savedOut );
                close $savedOut;

                die "Seek: STDERR: $!"
                  unless ($noredirect) || seek( STDERR, 0, 0 );
                $stderr = <STDERR> unless ($noredirect);
            };

            # Restore captured STDERR
            die( ( $@ || '' ) . " Can't close capturing STDERR: $!" )
              unless ($noredirect) || close(STDERR);
        };
        die( ( $@ || '' ) . " Can't restore saved STDERR: $!" )
          unless ($noredirect) || open( STDERR, '>&', $savedErr );
        close $savedErr unless ($noredirect);

        # sendmail in debug mode echoes the entire message - twice.
        # We'll remove that from the log.

        if ( $Foswiki::cfg{MailProgram} =~ m/(?:^|\b)sendmail(?:\b|$)/ ) {
            if ( $stderr =~ m/^(Please install an MTA.*)$/m ) {
                $neterrors .= $1;
            }
            my $stampre = qr/^(?:\d+\s+(<<<|>>>)\s+)/;
            my @lines = split( /\r?\n/, $stderr );

            # This could be an ugly RE, but a state machine is simpler
            $stderr = '';
            my $line;
            my $state = 0;
            while (@lines) {
                $line = shift @lines;
                if ( $state == 0 ) {
                    $stderr .= "$line\n";
                    if ( $line =~ m/$stampre/ ) {
                        $state = 1;
                    }
                    next;
                }
                if ( $state == 1 || $state == 3 ) {
                    if ( $line =~ m/$stampre$/ ) {
                        $stderr .= " ... Message contents ...\n";
                        $state++;
                        next;
                    }
                    $stderr .= $line . "\n";
                    next;
                }
                if ( $state == 2 ) {
                    next if ( $line !~ /$stampre\[EOF\]$/ );
                    $state++;
                }
                last if ( $line =~ m/$stampre\.$/ );
            }
            $stderr .= join( "\n", @lines );
        }
    }

    if ($neterrors) {
        $reporter->ERROR($neterrors);
    }

    if ( $neterrors || $Foswiki::cfg{SMTP}{Debug} ) {
        if ($stdout) {
            $reporter->NOTE( "Mailer output", $stdout );
        }
        if ($stderr) {
            $stderr =~ s/<a\s+/<a target="_blank" /gms;
            $reporter->NOTE( 'Transcript of e-mail server dialog', $stderr );
        }

        return if $neterrors;
    }

    $reporter->NOTE(<<ACCEPTED);
Mail was accepted for delivery to  $Foswiki::cfg{WebMasterName} &lt;$Foswiki::cfg{WebMasterEmail}&gt; from  "$fromName" &lt;$fromAddr&gt;.
Be sure to check any SPAM and Bulk-email folders before assuming that delivery has failed.
ACCEPTED
}

1;
__END__
Foswiki - The Free and Open Source Wiki, http://foswiki.org/

Copyright (C) 2014 Foswiki Contributors. Foswiki Contributors
are listed in the AUTHORS file in the root of this distribution.
NOTE: Please extend that file, not this notice.

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. For
more details read LICENSE in the root of this distribution.

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.

As per the GPL, removal of this notice is prohibited.
