NotifySend.php
[Pman.Core] / NotifySend.php
1 <?php
2 require_once 'Pman.php';
3
4 /**
5  * notification script sender - designed to be run by the Notify script - with many children running
6  * in parallel.
7  *
8  * called with an id of a core_notify element
9  *
10  * uses core_notify - to find an event to object and person.
11  *
12  * uses Events table to log failures
13  * 
14  * 
15  * calls $object->toEmail($person,$last_send, $notify) to generate an email struct with
16  *  array (
17  *      headers =>
18  *      recipients =>
19  *      body =>
20  *  )
21  * 
22  * 
23  */
24
25
26 class Pman_Core_NotifySend extends Pman
27 {
28     static $cli_desc = "Send out single notification email (usually called from  Core/Notify)";
29     
30     static $cli_opts = array(
31         'debug' => array(
32             'desc' => 'Turn on debugging (see DataObjects debugLevel )',
33             'default' => 0,
34             'short' => 'v',
35             'min' => 1,
36             'max' => 1,
37             
38         )
39     );
40     var $table = 'core_notify';
41     function getAuth()
42     {
43         $ff = HTML_FlexyFramework::get();
44         if (!$ff->cli) {
45             die("access denied");
46         }
47         //HTML_FlexyFramework::ensureSingle(__FILE__, $this);
48         return true;
49         
50     }
51    
52     function get($id,$opts)    
53     {
54         if ($opts['debug']) {
55             DB_DataObject::debugLevel($opts['debug']);
56         }
57         //DB_DataObject::debugLevel(1);
58         //date_default_timezone_set('UTC');
59         // phpinfo();exit;
60         
61         $w = DB_DataObject::factory($this->table);
62         
63         if (!$w->get($id)) {
64             die("invalid id or time\n");
65         }
66         if (strtotime($w->act_when) < strtotime($w->sent)) {
67             die("send repeat to early\n");
68         }
69          
70         $o = $w->object();
71         $p = $w->person();
72         
73         // let's work out the last notification sent to this user..
74         $l = DB_DataObject::factory($this->table);
75         $l->setFrom( array(
76                 'ontable' => $w->ontable,
77                 'onid' => $w->onid,
78                 'person_id' => $w->person_id,
79         ));        
80         $l->whereAdd('id != '. $w->id);
81         $l->orderBy('sent DESC');
82         $l->limit(1);
83         $ar = $l->fetchAll('sent');
84         $last = empty($ar) ? date('Y-m-d H:i:s', 0) : $ar[0];
85         
86         // find last event..
87         $ev = DB_DataObject::factory('Events');
88         $ev->on_id = $w->id;                           // int(11)
89         $ev->od_table = $this->table;
90         $ev->limit(1);
91         $ev->orderBy('event_when DESC');
92         $ar = $ev->fetchAll('event_when');
93         $last_event = empty($ar) ? 0 : $ar[0];
94         $next_try_min = 5;
95         if ($last_event) {
96             $next_try_min = floor((time() - strtotime($last_event)) / 60) * 2;
97         }
98         $next_try = $next_try_min . ' MINUTES';
99         
100         $email =  $this->makeEmail($o, $p,$last);
101         
102         
103         
104         //$p->email = 'alan@akbkhome.com'; //for testing..
105         //print_r($email);exit;
106         // should we fetch the watch that caused it.. - which should contain the method to call..
107         $dom = array_pop(explode('@', $p->email));
108         
109         $mxs = $this->mxs($dom);
110         $ww = clone($w);
111         
112         $fail = false;
113         require_once 'Mail.php';
114         
115         foreach($mxs as $dom) {
116             
117             $mailer = Mail::factory('smtp', array(
118                     'host'    => $dom ,
119                   //  'debug' => true
120                 ));
121             $res = $mailer->send($p->email, $email['headers'], $email['body']);
122             if ($res === true) {
123                 // success....
124                 
125                 $w->sent = date('Y-m-d H:i:s');
126                 $w->msgid = $email['headers']['Message-Id'];
127                 $w->event_id = -1; // sent ok.. - no need to record it..
128                 $w->update($ww);
129                 die(date('Y-m-d h:i:s') . " - SENT");
130             }
131             // what type of error..
132             list($code, $response) = $mailer->_smtp->getResponse();
133             if ($code < 0) {
134                 continue; // try next mx... ??? should we wait??? - nope we did not even connect..
135             }
136             // give up after 2 days..
137             if ($code == 421 && $next_try_min < (2*24*60)) {
138                 // try again later..
139                 // check last event for this item..
140                 $this->addEvent('NOTIFY', $w, 'GREYLISTED');
141                 $w->act_when = date('Y-m-d H:i:s', strtotime('NOW + 5 MINUTES'));
142                 $w->update($ww);
143                 die(date('Y-m-d h:i:s') . " - GREYLISTED");
144             }
145             $fail = true;
146             break;
147         }
148         if ($fail || $next_try_min > (2*24*60)) {
149         // fail.. = log and give up..
150             $id = $this->addEvent('NOTIFY', $w, 'FAILED - '. ($fail ? $res->toString() : "RETRY TIME EXCEEDED"));
151             $w->sent = date('Y-m-d H:i:s');
152             $w->msgid = '';
153             $w->event_id = $id;
154             $w->update($ww);
155             die(date('Y-m-d h:i:s') . ' - FAILED - '. ($fail ? $res->toString() : "RETRY TIME EXCEEDED"));
156         }
157         
158         $this->addEvent('NOTIFY', $w, 'NO HOST CAN BE CONTACTED');
159         $w->act_when = date('Y-m-d H:i:s', strtotime('NOW + 5 MINUTES'));
160         $w->update($ww);
161         die(date('Y-m-d h:i:s') ." - NO HOST AVAILABLE");
162
163         
164     }
165     function mxs($fqdn)
166     {
167         $mx_records = array();
168         $mx_weight = array();
169         $mxs = array();
170         if (!getmxrr($fqdn, $mx_records, $mx_weight)) {
171             return array($fqdn);
172         }
173         
174         asort($mx_weight,SORT_NUMERIC);
175         
176         foreach($mx_weight as $k => $weight) {
177             $mxs[] = $mx_records[$k];
178         }
179         return $mxs;
180     }
181     
182     /**
183      * wrapper to call object->toEmail()
184      * 
185      **/
186     function makeEmail($o, $p, $last)
187     {
188         return $o->toEmail($p,$last);
189     }
190 }