1: <?php
2: 3: 4:
5:
6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18: class Horde_Kolab_Filter_Transport
19: {
20: 21: 22: 23: 24:
25: var $_params;
26:
27: 28: 29: 30: 31:
32: var $_transport;
33:
34: 35: 36: 37: 38:
39: var $_got_newline;
40:
41: 42: 43:
44: function Horde_Kolab_Filter_Transport($params)
45: {
46: $this->_params = $params;
47: $this->_transport = false;
48: }
49:
50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
67: function &factory($driver, $params = array())
68: {
69: $class = 'Horde_Kolab_Filter_Transport_' . $driver;
70: if (!class_exists($class)) {
71: include dirname(__FILE__) . '/Transport/' . $driver . '.php';
72: }
73: if (class_exists($class)) {
74: $transport = new $class($params);
75: return $transport;
76: }
77: return PEAR::raiseError(sprintf('No such class \"%s\"', $class),
78: OUT_LOG | EX_SOFTWARE);
79: }
80:
81: 82: 83:
84: function createTransport() {
85: $this->_transport = $this->_createTransport();
86: }
87:
88: 89: 90: 91: 92: 93: 94: 95:
96: function start($sender, $recips)
97: {
98: $this->createTransport();
99:
100: $myclass = get_class($this->_transport);
101: $this->_got_newline = true;
102:
103: $result = $this->_transport->connect();
104: if (is_a($result, 'PEAR_Error')) {
105: $result->code = OUT_LOG | EX_UNAVAILABLE;
106: return $result;
107: }
108:
109: if (isset($this->_params['user']) && isset($this->_params['pass']) ) {
110: $this->_transport->auth($this->_params['user'], $this->_params['pass'], 'PLAIN');
111: }
112:
113: $result = $this->_transport->mailFrom($sender);
114: if (is_a($result, 'PEAR_Error')) {
115: $resp = $this->_transport->getResponse();
116: $error = PEAR::raiseError(sprintf('Failed to set sender: %s, code=%s',
117: $resp[1], $resp[0]), $resp[0]);
118: return $this->rewriteCode($error);
119: }
120:
121: if (!is_array($recips)) {
122: $recips = array($recips);
123: }
124:
125: $reciperrors = array();
126: foreach ($recips as $recip) {
127: $result = $this->_transport->rcptTo($recip);
128: if (is_a($result, 'PEAR_Error')) {
129: $resp = $this->_transport->getResponse();
130: $reciperrors[] = PEAR::raiseError(sprintf('Failed to set recipient: %s, code=%s',
131: $resp[1], $resp[0]), $resp[0]);
132: }
133: }
134:
135: if (count($reciperrors) == count($recips)) {
136:
137: if (count($reciperrors) == 1) {
138:
139: return $this->rewriteCode($reciperrors[0]);
140: }
141:
142: $error = $this->createErrorObject($reciperrors,
143: 'Delivery to all recipients failed!');
144: return $this->rewriteCode($error);
145: }
146:
147: $result = $this->_transport->_put('DATA');
148: if (is_a($result, 'PEAR_Error')) {
149: $resp = $this->_transport->getResponse();
150: $error = PEAR::raiseError(sprintf('Failed to send DATA: %s, code=%s',
151: $resp[1], $resp[0]), $resp[0]);
152: return $this->rewriteCode($error);
153: }
154:
155: $result = $this->_transport->_parseResponse(354);
156: if (is_a($result, 'PEAR_Error')) {
157: return $this->rewriteCode($result);
158: }
159:
160: if (!empty($reciperrors)) {
161: return $this->createErrorObject($reciperrors,
162: 'Delivery to some recipients failed!');
163: }
164: return true;
165: }
166:
167: 168: 169: 170: 171: 172: 173: 174:
175: function createErrorObject($reciperrors, $msg = null)
176: {
177: 178: 179:
180: if ($msg == null) {
181: $msg = 'Delivery to recipients failed.';
182: }
183:
184: $code = 1000;
185:
186: foreach ($reciperrors as $err) {
187: if ($err->code < $code) {
188: $code = $err->code;
189: }
190: }
191: return new PEAR_Error($msg, $code, null, null, $reciperrors);
192: }
193:
194: 195: 196: 197: 198: 199:
200: function quotedataline(&$data)
201: {
202: 203: 204: 205:
206: $data = preg_replace(array('/(?<!\r)\n/','/\r(?!\n)/'), "\r\n", $data);
207:
208: 209: 210: 211:
212: if ($this->_got_newline && !empty($data) && $data[0] == '.') {
213: $data = '.'.$data;
214: }
215:
216: $data = str_replace("\n.", "\n..", $data);
217: $len = strlen($data);
218: if ($len > 0) {
219: $this->_got_newline = ( $data[$len-1] == "\n" );
220: }
221: }
222:
223: 224: 225: 226: 227: 228: 229:
230: function data($data) {
231: $this->quotedataline($data);
232: $result = $this->_transport->_send($data);
233: if (is_a($result, 'PEAR_Error')) {
234: $resp = $this->_transport->getResponse();
235: $error = PEAR::raiseError(sprintf('Failed to send message data: %s, code=%s',
236: $resp[1], $resp[0]), $resp[0]);
237: return $this->rewriteCode($error);
238: }
239: return true;
240: }
241:
242: 243: 244: 245: 246:
247: function end()
248: {
249: if ($this->_got_newline) {
250: $dot = ".\r\n";
251: } else {
252: $dot = "\r\n.\r\n";
253: }
254:
255: $result = $this->_transport->_send($dot);
256: if (is_a($result, 'PEAR_Error')) {
257: $resp = $this->_transport->getResponse();
258: $error = PEAR::raiseError(sprintf('Failed to send message end: %s, code=%s',
259: $resp[1], $resp[0]), $resp[0]);
260: return $this->rewriteCode($error);
261: }
262: $result = $this->_transport->_parseResponse(250);
263: if (is_a($result, 'PEAR_Error')) {
264: return $this->rewriteCode($result);
265: }
266: $this->_transport->disconnect();
267: $this->_transport = false;
268: return true;
269: }
270:
271: 272: 273: 274: 275: 276: 277:
278: function rewriteCode($result)
279: {
280: list($resultcode, $resultmessage) = $this->_transport->getResponse();
281: if ($resultcode < 500) {
282: $code = EX_TEMPFAIL;
283: } else {
284: $code = EX_UNAVAILABLE;
285: }
286: $append = sprintf(': %s, original code %s', $resultmessage, $resultcode);
287: $result->message = $result->getMessage() . $append;
288: $result->code = OUT_LOG | OUT_STDOUT | $code;
289: return $result;
290: }
291:
292: }
293: