Thursday, August 11, 2016

Invoking External Commands within PowerShell

There are several ways to execute commands within PowerShell. One can use Invoke-Command cmdlet and the "&" call operator. But these cannot easily be used if the commands are built dynamically. Suppose that you are trying to gather up file names matching certain criteria with Get-ChildItem. Then you want to pass the collected names to another command depending on certain options.

Once you have the file list collected into an array, it can be passed as arguments to a command. For example:

$fileList = @()
Get-ChildItem -path "some-path" | ForEach-Object {
    if ($_.Length -gt 10MB) {
        $fileList += $_.FullName
    }
}
# now execute an external command
& zip.exe output.zip $fileList

A very nice bonus of using this method is that when $fileList is passed to the call operator, $fileList is expanded with spaces between items and quotes around the items that contain one or more spaces. For example, if $fileList contains two items

C:\Program Files\Paint\Paint.exe
D:\Temp\abc.txt

$fileList is going to be expanded as:

"C:\Program Files\Paint\Paint.exe" D:\Temp\abc.txt

The other options to use is Invoke-Expression cmdlet. However, it's notoriously difficult to build strings from an array to have quotes around the items that contain spaces.

Monday, August 8, 2016

Sending HTML Email from Perl

Sending email from perl is relatively an easy exercise. To send text email, you just need to use Net::SMTP like the following:

use Net::SMTP;

sub sendmail($$@)
{
    my $subj = shift;
    my $msg  = shift;
    my $smtp = Net::SMTP->new($o_smtpsvr);
    $subj = "Subject: $subj\n" unless $subj =~ /^Subject: /;
    $smtp->hello('MyDomain');
    $smtp->reset();
    $smtp->help('');
    $smtp->mail('noreply@xyz.com');
    $smtp->to(@_);
    $smtp->data($subj . $msg);
    $smtp->dataend();
    $smtp->quit;
}

sendmail('hello, world', 'my message', ('abc@xyz.com'));


If you wish to send HTML email instead, it gets a bit more complicated. The reason is that the message must be formatted in MIME. To do so, it's easier to use Email::MIME module from CPAN. Note that Email:MIME is not included with the standard perl distribution while Net::SMTP is.

use Email:MIME;
use Net::SMTP;

my $email_body =<<EOM;
<html>
<body>
Hello, world!
</body>
</html>
EOM

my $email = Email::MIME->create(
    header_str => [
         To      => $email_to,
         Cc      => $email_cc,
         From    => $email_from,
         Subject => $email_subject
    ],
    body_str   => $email_body,
    attributes => {
         content_type => 'text/html',
         charset => 'utf8',
         encoding => 'quoted-printable'
    }
);

my $smtp = Net::SMTP->new($SmtpHostName);
$smtp->hello('MyDomain');
$smtp->reset();
$smtp->help('');
$smtp->mail($email_from);
$smtp->to($email_to);
$smtp->data($email->as_string);
$smtp->dataend();
$smtp->quit;