use Mail::Sender;
use Getopt::Simple;

#settings
$default_from = 'foo@bar.com';
$default_name = 'Foo Bar';
$server       = 'localhost';
#$authtype     = 'CRAM-MD5';
#$user         = 'tw@zentrifuge.biz';
#$pass         = '***';

#get parameters

my $options = {
	from => {
		type    => '=s',
		env     => '$USER',
		default => $ENV{USER},
		verbose => 'The sender\'s address',
		order   => 1,
	},
	name => {
		type    => '=s',
		env     => '$USER',
		default => $ENV{USER},
		verbose => 'The sender\'s name',
		order   => 2,
	},
	to => {
		type    => '=s',
		env     => '-',
		default => undef,
		verbose => 'The recipient\'s email address',
		order   => 3,
	},
	subject => {
		type    => '=s',
		env     => '-',
		default => '(no subject)',
		verbose => 'The subject',
		order   => 4,
	},
};

my $opt = Getopt::Simple->new();

unless ($opt->getOptions($options, "Usage: $0 [options]")) {
	exit -1;
}

$/ = undef;
my $text = 'foobar';#<>;
#send mail
mail_smtp($$opt{switch}{subject}, $text, $$opt{switch}{to}, undef, undef, $$opt{switch}{from}, $$opt{switch}{name});

=head2 mail_smtp

Uses L<Mail::Sender> for SMTP, which in turn uses L<Digest::HMAC_MD5> for auth
type C<CRAM-MD5> and L<Authen::NTLM> for auth type NTLM.
So you might want to install those modules, if you use these auth types.

=over

=item * $subject - The mail's subject

=item * $text    - The body

=item * $to      - The recipient

=item * ($cc)    - Optional: Carbon copy

=item * ($bcc)   - Optional: Blind carbon copy

=item * ($from)  - The senders email address (e.g. john@doe.com).
If not specified the defaults from your settings will be used.

=item * ($FROM)  - The sender full name (e.g. "John Doe")
If not specified the defaults from your settings will be used.

=back

=cut
sub mail_smtp {
	my ($subject, $text, $to, $cc, $bcc, $from, $FROM) = @_;
	
	#default settings
	$from   ||= $default_from;
	$FROM   ||= $default_name;
	my $auth  = $authtype;
	
	#build from-header
	$from = "\"$FROM\" <$from>" if defined $FROM;
	
	#create sender object
	my $sender = Mail::Sender->new({
		from    => $from,
#		replyto => $from,
		to      => $to,
		cc      => $cc,
		bcc     => $bcc,
		subject => $subject,

		smtp    => $server,
		authid  => $user,
		authpwd => $pass
	});
	
	warn $server;
	
	#get supported auth protocols
	my %supported_auth_types = map { $_ => 1 } $sender->QueryAuthProtocols();
	#add UNDEF (= no auth) to the server supported auth methods
	$supported_auth_types{UNDEF} = 1;
	#connection error?
	if (defined $sender->{'error'}) {
		die "Couldn't get supported authentication methods/connect to SMTP server '$server'! " . $sender->{'error_msg'};
	}
	
	#determine auth types to try
	undef $auth if not $auth or not length $auth;
	my @auth_types;
	if (defined $user and defined $pass) {
		#auth required
		if (defined $auth) {
			#predefined auth
			@auth_types = (uc $auth);
		} else {
			#try all auth types
			@auth_types = qw/CRAM-MD5 NTLM LOGIN PLAIN UNDEF/;
		}
		
		#create intersection of server supported auth types and client
		my @intersection;
		foreach my $type (@auth_types) {
			push @intersection, $type if ($supported_auth_types{$type});
		}
		@auth_types = @intersection;
	} else {
		#no auth!
		@auth_types = ('UNDEF');
	}
	
	#put error message when there are no matching auth types
	unless (@auth_types) {
		die "No available authentication methods (matching your settings)! Cannot send.";
	}
	
	#try all supported auth types
	my $sent = 0;
	foreach my $type (@auth_types) {
		eval {
			delete $sender->{auth};
			$sender->{auth} = $type unless $type eq 'UNDEF';
			#send mail
			my $rv = $sender->MailMsg({ msg => $text });
			#check return value
			if (ref $rv) {
				#success
				$sent = 1;
			} else {
				#error
				die "Error (auth method $type): $sender->{error_msg} (code $sender->{error})";
			}
		};
		#errors in eval
		if ($@) {
			chomp $@;
			$Konstrukt::Debug->error_message("Error: $@") if Konstrukt::Debug::ERROR;
		}
		#exit the loop, if successfully sent
		last if $sent;
	}
	
	#put error message it no method succeeded:
	die "Could not send your email! No authentication method succeeded." if not $sent;
	
	return $sent;
}
#= /mail_smtp
