<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># Copyright 1999-2006, Fred Steinberg, Brown Bear Software

# MailNotifier.pm

use strict;
package MailNotifier;

use Calendar::Mail::MailSender;
use Calendar::Event;
use Calendar::EventFormatter;
use Calendar::MasterDB;         # for mail prefs
use Calendar::User;
use CGI (':standard');

# Pass an Operation, Event, Date, and true for edited event, otherwise new
sub send {
#    my ($class, $op, $event, $date, $editedP) = @_;
    my $class = shift;
    my %args = (op     =&gt; undef,
                event  =&gt; undef,
                date   =&gt; undef,
                edited =&gt; undef,
                TO     =&gt; undef,
                CC     =&gt; undef,
                BCC    =&gt; undef,
                @_);
    my $op      = $args{op};
    my $event   = $args{event};
    my $date    = $args{date};
    my $editedP = $args{edited};

    my $i18n    = $op-&gt;I18N;
    my $calName = $op-&gt;calendarName;
    my $prefs   = $op-&gt;prefs;
    my $cgi     = CGI-&gt;new;

    my $self = {};
    bless $self, $class;
    $self-&gt;{event} = $event;

    my $subject;
    if (defined $editedP) {
        $subject = $prefs-&gt;NotifyModSubject;
        $subject ||= $i18n-&gt;get ('Calcium event modified');
    } else {
        $subject = $prefs-&gt;NotifyNewSubject;
        $subject ||= $i18n-&gt;get ('Calcium event added');
    }

    # check for TZ offset
    # Get first address; if &gt; 1 in list, just use TZ of first....
    my $offset;
    if ($event-&gt;mailTo) {
        $event-&gt;mailTo =~ /([^, ]*)/;
        my $address = $1;
        if (my $user = User-&gt;userFromAddress ($address)) {
            $offset = $user-&gt;timezone || 0;
        }
    }
    if (!defined $offset) {
        $offset = $prefs-&gt;DefaultTimezone;
        $offset ||= 0;
    }
    my $dateChange = $event-&gt;adjustForTimezone ($date, $offset);
    my $theDate = $date + $dateChange;

    my $prettyDate = $theDate-&gt;pretty ($i18n),
    my $time = $event-&gt;getTimeString ('both', $prefs);

    # Evaluate special strings in the subject
    $subject = $event-&gt;expandString ($subject, $date, $i18n);
    $subject =~ s/[\r\n]/ /g; # remove newlines or mail gets munged

    my %header = (text =&gt; "Calcium Event Notification\n$prettyDate" .
                          ($time ? "\n$time\n" : ''),
                  html =&gt; $cgi-&gt;table ({bgcolor =&gt; 'yellow'},
#                                        width   =&gt; '100%'},
                                       Tr (td (b ('Event Notification')),
                                           td ($prettyDate),
                                           ($time ? td ($time) : ''))));

    my @links;
    my $url = $op-&gt;makeURL ({FullURL =&gt; 1,
                             Op      =&gt; 'ShowIt',
                             Date    =&gt; "$date"});
    $url =~ s/localhost/$ENV{SERVER_NAME}/;
    push @links, {text =&gt; "\nA link to the '$calName' calendar:\n$url\n",
                  html =&gt; 'Go to the ' .
                          $cgi-&gt;a ({href =&gt; $url}, "$calName calendar")};

    if (($prefs-&gt;MailAddLink || '') !~ /hide/) {
        my $prompt = $i18n-&gt;get ("Add this event to your web calendar");

        my %repHash;
        if ($event-&gt;isRepeating) {
            my $info = $event-&gt;repeatInfo;
            my $endDate = ($info-&gt;endDate == Date-&gt;openFuture ? undef
                                                             : $info-&gt;endDate);
            my $period = $info-&gt;period;
            if (ref $period) {
                $period = join (' ', @$period);
            }

            my $monthWeek = $info-&gt;monthWeek;
            if (ref $monthWeek) {
                $monthWeek = join (' ', @$monthWeek);
            }

            my $exList = join (' ', map {"$_"} @{$info-&gt;exclusionList});
            $exList ||= undef;      # don't want ''
            %repHash = (Repeat       =&gt; 1,
                        EndDate      =&gt; $endDate,
                        Period       =&gt; $period,
                        Frequency    =&gt; $info-&gt;frequency,
                        MonthWeek    =&gt; $monthWeek,
                        MonthMonth   =&gt; $info-&gt;monthMonth,
                        SkipWeekends =&gt; $info-&gt;skipWeekends,
                        Exclusions   =&gt; $exList
                       );
        }

        my ($primaryCat, @moreCats) = $event-&gt;getCategoryList;

        # Avoid huge URLs; truncate text at 500 chars, Details at 2000
        my $text = $event-&gt;text;
        if (length ($text) &gt; 500) {
            $text = substr ($text, 0, 500);
            $prompt .= ' (' . $i18n-&gt;get ("Event text truncated") . ')';
        }
        my $details = $event-&gt;popup || $event-&gt;link;
        if ($details and length ($details) &gt; 2000) {
            $details = substr ($details, 0, 2000);
            $prompt .= ' (' . $i18n-&gt;get ("Event details truncated") . ')';
        }

        $url = $op-&gt;makeURL ({FullURL    =&gt; 1,
                              Op         =&gt; 'AddEventExternal',
                              CalendarName =&gt; undef,
                              Date       =&gt; "$date",
                              Text       =&gt; $text,
                              Details    =&gt; $details,
                              StartTime  =&gt; $event-&gt;startTime,
                              EndTime    =&gt; $event-&gt;endTime,
                              TimePeriod =&gt; $event-&gt;timePeriod,
                              Category   =&gt; $primaryCat,
                              %repHash});

        foreach (@moreCats) {
            $url .= '&amp;MoreCategories=' . $cgi-&gt;escape ($_);
        }

        $url =~ s/localhost/$ENV{SERVER_NAME}/;

        push @links, {text =&gt; "\n$prompt:\n$url\n",
                      html =&gt; $cgi-&gt;a ({href =&gt; $url}, $prompt)};
    }

    my $addedComments = $event-&gt;mailText || '';
    if ($prefs-&gt;EventHTML =~ /none/i) {
        $addedComments =~ s/&lt;/&amp;lt;/g;    # Escape HTML if we don't want it
        $addedComments =~ s/&gt;/&amp;gt;/g;
    }
    $addedComments =~ s/\r//g;  # remove ^Ms

    my $modOrEdit = $editedP ? 'Modified by' : 'Created by';
    my $user = $op-&gt;getUsername || 'Anonymous User';
    my $comments = $addedComments ? "Comments: $addedComments" : '';

    my ($fromAddr, $userObj);
    $userObj  = User-&gt;getUser ($user) if (defined $user);
    $fromAddr = $userObj-&gt;email if ($userObj);

    my $commentsRow = '';
    if ($addedComments) {
        $commentsRow = Tr ({-valign =&gt; 'top'},
                           td (b ($i18n-&gt;get ('Comments:'))),
                           td (Event::_escapeThis ($addedComments,
                                                   undef, 1)));
    }
    my $userTable = table (Tr (td (b ($modOrEdit . ':')),
                               td ($user)),
                           $commentsRow);
    my %userID = (text =&gt; "$modOrEdit $user\n$comments\n",
                  html =&gt; $userTable);

    my $repeat = '';
    if ($event-&gt;isRepeating) {
        my $frequency = $event-&gt;repeatInfo-&gt;frequency;
        if ($frequency) {
            $repeat = $i18n-&gt;get ('This event repeats every') . ' ';
            my $label = (qw (0 0
                             other third fourth fifth sixth))[$frequency];
            $repeat .= ($i18n-&gt;get ($label) . ' ') if $label;

            my $period = $event-&gt;repeatInfo-&gt;period;
            if (ref ($period) eq 'ARRAY') {
                my @days = map {$i18n-&gt;get (Date-&gt;dayName ($_))} @$period;
                $repeat .= join ', ', @days;
            } elsif ($period) { # something like 'week'
                $period = 'day' if ($period eq 'dayBanner');
                $repeat .= $i18n-&gt;get ($period);
            }
        } else {
            $repeat = $i18n-&gt;get ('This event repeats on the') . ' ';
            my @weeks = @{$event-&gt;repeatInfo-&gt;monthWeek};
            $repeat .= join (' ' . $i18n-&gt;get ('and') . ' ',
                           map {(qw (undef
                                     first second third fourth last))[$_]}
                           @weeks);
            $repeat .= ' ';
            $repeat .= $i18n-&gt;get (Date-&gt;dayName
                                              ($event-&gt;repeatInfo-&gt;monthDay));
            $repeat .= ' ' . $i18n-&gt;get ('every') . ' ';
            my $freq = (qw (0 0 second third fourth fifth sixth seventh
                            eighth ninth tenth eleventh twelfth))
                                            [$event-&gt;repeatInfo-&gt;monthMonth];
            $repeat .= $freq ? $i18n-&gt;get ($freq) : '';
            $repeat .= ' ' . $i18n-&gt;get ('month');
        }
        my $end = $event-&gt;repeatInfo-&gt;endDate;
        if ($end == Date-&gt;openFuture) {
            $repeat .= ' ' . $i18n-&gt;get ('forever') . ".\n";
        } else {
            $repeat .= ' ' . $i18n-&gt;get ('until') . ' ';
            $repeat .= $end-&gt;pretty ($i18n) . "\n";
        }
    }

    my ($textBody, $htmlBody) = $event-&gt;formatForMail ($theDate, $calName,
                                                       $prefs, $i18n);
    if ($repeat) {
        $textBody .= "\n$repeat";
        $htmlBody .= "&lt;p&gt;$repeat&lt;/p&gt;";
    }

    my %info = (text =&gt; $textBody, html =&gt; $htmlBody);

    my $mPrefs = Preferences-&gt;new (MasterDB-&gt;new);
    my %params;
    $params{To}  = $args{TO}  if defined $args{TO};
    $params{CC}  = $args{CC}  if defined $args{CC};
    $params{BCC} = $args{BCC} if defined $args{BCC};
    $params{SMTP} = $mPrefs-&gt;MailSMTP if defined $mPrefs-&gt;MailSMTP;
    $params{From} = $fromAddr ||
                    $prefs-&gt;MailFrom ||
                    (defined ($mPrefs-&gt;MailFrom) &amp;&amp; $mPrefs-&gt;MailFrom) ||
                    "calcium\@$ENV{SERVER_NAME}";

    my ($plainText, $htmlText);
    foreach (\%header, \%userID, \%info) {
        $plainText .= $_-&gt;{text} . "\n";
        $htmlText  .= $_-&gt;{html} . '&lt;hr align="left" width="25%"&gt;';
    }
    foreach (@links) {
        $plainText .= $_-&gt;{text} . "\n";
        $htmlText  .= $_-&gt;{html} . '&lt;hr align="left" width="25%"&gt;';
    }

    my $sig = ($prefs-&gt;MailSignature || $mPrefs-&gt;MailSignature || '');
    $sig =~ s/\r//g;

    $plainText .= "\n";
    $plainText .= $sig;

    $htmlText  = '&lt;!DOCTYPE HTML PUBLIC ' .
                 '"-//W3C//DTD HTML 4.0 Transitional//EN"' . "\n" .
                 '        "http://www.w3.org/TR/REC-html40/loose.dtd"&gt;' .
                 "\n&lt;html&gt;&lt;head&gt;&lt;title&gt;Calcium Email Notification&lt;/title&gt;" .
                 "&lt;/head&gt;\n&lt;body&gt;$htmlText" .
                 (Event::_escapeThis ($sig, undef, 1) || '')
                 . "&lt;/body&gt;&lt;/html&gt;\n";

    my $mailer = MailSender-&gt;new (%params);

    my $format = $prefs-&gt;MailFormat || 'both';
    my %contents = (text =&gt; $plainText,
                    html =&gt; $htmlText);
    if (lc ($format) eq 'text') {
        delete $contents{html};
    } elsif (lc ($format) eq 'html') {
        delete $contents{text};
    }

    if (lc ($prefs-&gt;MailiCalAttach || 'include') eq 'include') {
        require Calendar::EventvEvent;
        require Calendar::vCalendar::vCalendar;
        my $vevent = $event-&gt;vEvent ($date);
        my $vCal = vCalendar-&gt;new (events  =&gt; [$vevent],
                                   version =&gt; '2.0');
        my $vcaltext = $vCal-&gt;textDump (METHOD =&gt; 'PUBLISH');
        $vcaltext =~ s/\r//g;
        $contents{attachment} = {type        =&gt; 'text/calendar',
                               encoding    =&gt; '7bit',
                               disposition =&gt;
                                    'attachment; filename="CalciumEvent.ics"',
                               contents    =&gt; $vcaltext};
    }

    my $ok = $mailer-&gt;send ($subject, \%contents);

    die "Mail notification failed! " . $mailer-&gt;error . "\n" unless $ok;
    $self;
}

1;
</pre></body></html>