1 # Copyright (C) 2012-2013 W. Trevor King <wking@tremily.us>
3 # This file is part of rss2email.
5 # rss2email is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 2 of the License, or (at your option) version 3 of
10 # rss2email is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along with
15 # rss2email. If not, see <http://www.gnu.org/licenses/>.
17 """rss2email-specific errors
22 from . import LOG as _LOG
23 from . import __version__, __url__, __email__
25 import pprint as _pprint
27 import feedparser as _feedparser
28 import html2text as _html2text
31 class RSS2EmailError (Exception):
32 def __init__(self, message):
33 super(RSS2EmailError, self).__init__(message)
37 if self.__cause__ is not None:
38 _LOG.error('cause: {}'.format(self.__cause__))
41 class TimeoutError (RSS2EmailError):
42 def __init__(self, time_limited_function, message=None):
44 if time_limited_function.error is not None:
46 'error while running time limited function: {}'.format(
47 time_limited_function.error[1]))
49 message = '{} second timeout exceeded'.format(
50 time_limited_function.timeout)
51 super(TimeoutError, self).__init__(message=message)
52 self.time_limited_function = time_limited_function
55 class NoValidEncodingError (RSS2EmailError, ValueError):
56 def __init__(self, string, encodings):
57 message = 'no valid encoding for {} in {}'.format(string, encodings)
58 super(NoValidEncodingError, self).__init__(message=message)
60 self.encodings = encodings
63 class SMTPConnectionError (ValueError, RSS2EmailError):
64 def __init__(self, server, message=None):
66 message = 'could not connect to mail server {}'.format(server)
67 super(SMTPConnectionError, self).__init__(message=message)
71 super(SMTPConnectionError, self).log()
73 'check your config file to confirm that smtp-server and other '
74 'mail server settings are configured properly')
75 if hasattr(self.__cause__, 'reason'):
76 _LOG.error('reason: {}'.format(self.__cause__.reason))
79 class SMTPAuthenticationError (SMTPConnectionError):
80 def __init__(self, server, username):
82 'could not authenticate with mail server {} as user {}'.format(
84 super(SMTPAuthenticationError, self).__init__(
85 server=server, message=message)
86 self.username = username
89 class IMAPConnectionError (ValueError, RSS2EmailError):
90 def __init__(self, server, port, message=None):
92 message = 'could not connect to mail server {}:{}'.format(
94 super(IMAPConnectionError, self).__init__(message=message)
99 super(IMAPConnectionError, self).log()
101 'check your config file to confirm that imap-server and other '
102 'mail server settings are configured properly')
103 if hasattr(self.__cause__, 'reason'):
104 _LOG.error('reason: {}'.format(self.__cause__.reason))
107 class IMAPAuthenticationError (IMAPConnectionError):
108 def __init__(self, server, port, username):
110 'could not authenticate with mail server {}:{} as user {}'.format(
111 server, port, username))
112 super(IMAPAuthenticationError, self).__init__(
113 server=server, port=port, message=message)
114 self.username = username
117 class SendmailError (RSS2EmailError):
118 def __init__(self, status=None, stdout=None, stderr=None):
120 message = 'sendmail exited with code {}'.format(status)
123 super(SendmailError, self).__init__(message=message)
129 super(SendmailError, self).log()
131 'Error attempting to send email via sendmail. You may need '
132 'to configure rss2email to use an SMTP server. Please refer '
133 'to the rss2email documentation or website ({}) for complete '
134 'documentation.').format(__url__))
137 class FeedError (RSS2EmailError):
138 def __init__(self, feed, message=None):
140 message = 'error with feed {}'.format(feed.name)
141 super(FeedError, self).__init__(message=message)
145 class InvalidFeedConfig (FeedError):
146 def __init__(self, setting, feed, message=None, **kwargs):
148 message = "invalid feed configuration {}".format(
149 {setting: getattr(feed, setting)})
150 super(InvalidFeedConfig, self).__init__(
151 feed=feed, message=message, **kwargs)
152 self.setting = setting
155 class InvalidFeedName (InvalidFeedConfig):
156 def __init__(self, name, **kwargs):
157 message = "invalid feed name '{}'".format(name)
158 super(InvalidFeedName, self).__init__(
159 setting='name', message=message, **kwargs)
162 class ProcessingError (FeedError):
163 def __init__(self, parsed, feed, message=None, **kwargs):
165 message = 'error processing feed {}'.format(feed)
166 super(ProcessingError, self).__init__(feed=feed, message=message)
170 super(ProcessingError, self).log()
171 if type(self) == ProcessingError: # not a more specific subclass
173 '=== rss2email encountered a problem with this feed ===')
175 '=== See the rss2email FAQ at {} for assistance ==='.format(
178 '=== If this occurs repeatedly, send this to {} ==='.format(
181 'error: {} {}'.format(
182 self.parsed.get('bozo_exception', "can't process"),
184 _LOG.warning(_pprint.pformat(self.parsed))
185 _LOG.warning('rss2email {}'.format(__version__))
186 _LOG.warning('feedparser {}'.format(_feedparser.__version__))
187 _LOG.warning('html2text {}'.format(_html2text.__version__))
188 _LOG.warning('Python {}'.format(_sys.version))
189 _LOG.warning('=== END HERE ===')
192 class HTTPError (FeedError):
193 def __init__(self, status, feed, **kwargs):
194 message = 'HTTP status {} fetching feed {}'.format(status, feed)
195 super(HTTPError, self).__init__(feed=feed, message=message)
199 class FeedsError (RSS2EmailError):
200 def __init__(self, feeds=None, message=None, **kwargs):
202 message = 'error with feeds'
203 super(FeedsError, self).__init__(message=message, **kwargs)
207 class DataFileError (FeedsError):
208 def __init__(self, feeds, message=None):
210 message = 'problem with the feed data file {}'.format(
212 super(DataFileError, self).__init__(feeds=feeds, message=message)
215 class NoDataFile (DataFileError):
216 def __init__(self, feeds):
217 message = 'feed data file {} does not exist'.format(feeds.datafile)
218 super(NoDataFile, self).__init__(feeds=feeds, message=message)
221 super(NoDataFile, self).log()
223 "if you're using r2e for the first time, you have to run "
227 class NoToEmailAddress (InvalidFeedConfig, FeedsError):
228 def __init__(self, feed, **kwargs):
229 message = 'no target email address has been defined'
230 super(NoToEmailAddress, self).__init__(
231 setting='to', feed=feed, message=message, **kwargs)
234 super(NoToEmailAddress, self).log()
236 "please run 'r2e email emailaddress' or "
237 "'r2e add name url emailaddress'.")
240 class FeedIndexError (FeedsError, IndexError):
241 def __init__(self, index, message=None, **kwargs):
243 message = 'feed {!r} not found'.format(index)
244 super(FeedIndexError, self).__init__(
245 message=message, **kwargs)
249 class OPMLReadError (RSS2EmailError):
250 def __init__(self, **kwargs):
251 message = 'error reading OPML'
252 super(OPMLReadError, self).__init__(message=message, **kwargs)