feed2email 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +37 -28
- data/TODO.md +4 -1
- data/bin/feed2email +6 -1
- data/lib/feed2email/config.rb +9 -7
- data/lib/feed2email/core_ext.rb +6 -0
- data/lib/feed2email/entry.rb +4 -0
- data/lib/feed2email/feed.rb +39 -35
- data/lib/feed2email/lazy_smtp_connection.rb +34 -0
- data/lib/feed2email/logger.rb +8 -25
- data/lib/feed2email/mail.rb +26 -31
- data/lib/feed2email/version.rb +1 -1
- data/lib/feed2email.rb +14 -10
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f18bbfd4e8a09cb263f70c7966af0fa9e6602a3c
|
4
|
+
data.tar.gz: fe00a0445e6010eca1d847861f33687beb7a8dc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fddbfd1416024208e32e65ba16a5eeb51c3e6537d6b39d0e49ba945ae8ab5c9bf9c8c14f3e976b173da9f06976e15b54ebc18ac73c62250727f2e3a58eafa1b
|
7
|
+
data.tar.gz: 0f1cbbdcba1768b9f75ad29c21b3c5c4d17cd55446dbaa1aed49fc72d9b63ec58a3c333dd1d8a0001e31f9cc6555ac106a8c40db764bcc127b004a2e0605f69c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
### 0.7.0
|
2
|
+
|
3
|
+
* Prevent simultaneous running instances
|
4
|
+
* Support log rotation
|
5
|
+
* Show entry author and pubdate in email
|
6
|
+
* Use a single SMTP connection for all email sending
|
7
|
+
* Rename `smtp_tls` option to `smtp_starttls`
|
8
|
+
|
1
9
|
### 0.6.0
|
2
10
|
|
3
11
|
* Render text/plain body as Markdown
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# feed2email
|
1
|
+
# feed2email [![Gem Version](https://badge.fury.io/rb/feed2email.svg)](http://badge.fury.io/rb/feed2email)
|
2
2
|
|
3
3
|
RSS/Atom feed updates in your email
|
4
4
|
|
@@ -7,9 +7,11 @@ RSS/Atom feed updates in your email
|
|
7
7
|
I don't like having a separate application for feeds when I'm already checking
|
8
8
|
my email. I also never read a thing when feeds are kept in a separate place.
|
9
9
|
|
10
|
-
feed2email
|
11
|
-
|
10
|
+
feed2email is a [headless][] RSS/Atom feed aggregator that sends feed entries
|
11
|
+
via email. It was written primarily as a replacement of [rss2email][] and aims
|
12
|
+
to be simple, fast and easy to use.
|
12
13
|
|
14
|
+
[headless]: http://en.wikipedia.org/wiki/Headless_software
|
13
15
|
[rss2email]: http://www.allthingsrss.com/rss2email/
|
14
16
|
|
15
17
|
## Installation
|
@@ -27,13 +29,7 @@ $ gem install feed2email
|
|
27
29
|
|
28
30
|
Through a [YAML][] file at `~/.feed2email/config.yml`.
|
29
31
|
|
30
|
-
It is possible to send email via SMTP or an [MTA][] (default). If `config.yml`
|
31
|
-
contains options for both, feed2email will use SMTP.
|
32
|
-
|
33
32
|
[YAML]: http://en.wikipedia.org/wiki/YAML
|
34
|
-
[MTA]: http://en.wikipedia.org/wiki/Message_transfer_agent
|
35
|
-
|
36
|
-
### Format
|
37
33
|
|
38
34
|
Each line in the configuration file contains a key-value pair. Each key-value
|
39
35
|
pair is separated with a colon: `foo: bar`
|
@@ -48,9 +44,20 @@ pair is separated with a colon: `foo: bar`
|
|
48
44
|
`true` which logs to standard output; use `false` to disable logging)
|
49
45
|
* `log_level` (optional) is the logging verbosity level and can be `fatal`
|
50
46
|
(least verbose), `error`, `warn`, `info` (default) and `debug` (most verbose)
|
47
|
+
* `log_shift_age` (optional) is the number of _old_ log files to keep or the
|
48
|
+
frequency of rotation (`daily`, `weekly`, `monthly`; default is `0` so only
|
49
|
+
the current log file is kept)
|
50
|
+
* `log_shift_size` (optional) is the maximum log file size in _megabytes_ and it
|
51
|
+
only applies when `log_shift_age` is a number greater than zero (default is
|
52
|
+
`1`)
|
51
53
|
* `max_entries` (optional) is the maximum number of entries to process per feed
|
52
54
|
(default is `20`; use `0` for unlimited)
|
53
55
|
|
56
|
+
It is possible to send email via SMTP or an [MTA][] (default). If `config.yml`
|
57
|
+
contains options for both, feed2email will use SMTP.
|
58
|
+
|
59
|
+
[MTA]: http://en.wikipedia.org/wiki/Message_transfer_agent
|
60
|
+
|
54
61
|
### SMTP
|
55
62
|
|
56
63
|
For this method you need to have access to an SMTP service. [Mailgun][] has a
|
@@ -61,21 +68,22 @@ free plan.
|
|
61
68
|
* `smtp_user` (required) is the username of your email account
|
62
69
|
* `smtp_pass` (required) is the password of your email account (see the warning
|
63
70
|
below)
|
64
|
-
* `
|
71
|
+
* `smtp_starttls` (optional) controls STARTTLS (default is `true`; can also be
|
72
|
+
`false`)
|
65
73
|
* `smtp_auth` (optional) controls the authentication method (default is `login`;
|
66
74
|
can also be `plain` or `cram_md5`)
|
67
75
|
|
68
76
|
**Warning:** Unless it has correct restricted permissions, anyone with access in
|
69
77
|
your system will be able to read `config.yml` and your password. To prevent
|
70
78
|
this, feed2email will not run and complain if it detects the wrong permissions.
|
71
|
-
|
79
|
+
To set the correct permissions, issue `chmod 600 ~/.feed2email/config.yml`
|
72
80
|
|
73
81
|
[Mailgun]: http://www.mailgun.com/
|
74
82
|
|
75
83
|
### MTA
|
76
84
|
|
77
85
|
For this method you need to have an [MTA][] with a [Sendmail][]-compatible
|
78
|
-
interface
|
86
|
+
interface set up and working in your system like [msmtp][] or [Postfix][].
|
79
87
|
|
80
88
|
* `sendmail_path` (optional) is the path to the Sendmail binary (default is
|
81
89
|
`/usr/sbin/sendmail`)
|
@@ -88,26 +96,20 @@ interface setup and working in your system like [msmtp][] or [Postfix][].
|
|
88
96
|
|
89
97
|
### Managing feeds
|
90
98
|
|
91
|
-
Create `~/.feed2email/feeds.yml` and add the
|
99
|
+
Create or edit `~/.feed2email/feeds.yml` and add the URL of the feed you want to
|
92
100
|
subscribe to, prefixed with a dash and a space:
|
93
101
|
|
94
102
|
~~~ yaml
|
95
103
|
- https://github.com/agorf/feed2email/commits.atom
|
96
104
|
~~~
|
97
105
|
|
98
|
-
To disable a feed, comment it:
|
106
|
+
To disable a feed, comment its line by prefixing it with a hash symbol:
|
99
107
|
|
100
108
|
~~~ yaml
|
101
109
|
#- https://github.com/agorf/feed2email/commits.atom
|
102
110
|
~~~
|
103
111
|
|
104
|
-
### Running
|
105
|
-
|
106
|
-
Simply:
|
107
|
-
|
108
|
-
~~~ sh
|
109
|
-
$ feed2email
|
110
|
-
~~~
|
112
|
+
### Running for the first time
|
111
113
|
|
112
114
|
When feed2email runs for the first time or after adding a new feed:
|
113
115
|
|
@@ -121,14 +123,14 @@ provided migration script: `feed2email-migrate-history` If you don't, feed2email
|
|
121
123
|
will think it's run for the first time and will treat all entries as old (thus
|
122
124
|
no email will be sent and you may miss some entries).
|
123
125
|
|
124
|
-
|
126
|
+
### Receiving specific entries from a feed
|
125
127
|
|
126
|
-
1. Add
|
128
|
+
1. Add the feed URL to `~/.feed2email/feeds.yml`
|
127
129
|
1. Run feed2email once so that the feed's history file is generated
|
128
130
|
1. Remove the entries you want to receive from the feed's history (i.e. with
|
129
131
|
your text editor)
|
130
|
-
1. Remove the feed's meta file (`meta-<digest>.yml
|
131
|
-
caching
|
132
|
+
1. Remove the feed's meta file (`meta-<digest>.yml`, where `<digest>` is the MD5
|
133
|
+
hex digest of the feed URL) to bust feed fetching caching
|
132
134
|
|
133
135
|
Next time feed2email runs, these entries will be treated as new and will be
|
134
136
|
processed (sent as email).
|
@@ -138,12 +140,19 @@ processed (sent as email).
|
|
138
140
|
Before processing each feed, feed2email issues a [HEAD request][] to check
|
139
141
|
whether it has been permanently moved by looking for a _301 Moved Permanently_
|
140
142
|
HTTP status and its respective _Location_ header. In such case, feed2email
|
141
|
-
updates
|
142
|
-
email sent). If you do want to have some of them sent as email,
|
143
|
-
|
143
|
+
updates `~/.feed2email/feeds.yml` with the new location and all feed entries are
|
144
|
+
skipped (no email sent). If you do want to have some of them sent as email, see
|
145
|
+
[Receiving specific entries from a feed](#receiving-specific-entries-from-a-feed).
|
144
146
|
|
145
147
|
[HEAD request]: http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods
|
146
148
|
|
149
|
+
### Feed caching
|
150
|
+
|
151
|
+
feed2email caches fetched feeds with the _Last-Modified_ and _Etag_ HTTP
|
152
|
+
headers. If you want to force a feed to be fetched, remove the feed's meta file
|
153
|
+
(`~/.feed2email/meta-<digest>.yml`, where `<digest>` is the MD5 hex digest of
|
154
|
+
the feed URL). Next time feed2email runs, the feed will be fetched.
|
155
|
+
|
147
156
|
### Automating
|
148
157
|
|
149
158
|
You can use [cron][] to run feed2email automatically e.g. once every hour.
|
data/TODO.md
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
* Specs
|
4
4
|
* Do not mark entry as sent if email was not sent
|
5
|
-
* Show entry metadata in email (e.g. pubdate, author)
|
6
5
|
* Implement a command-line interface to manage feeds.yml
|
7
6
|
* Detect entry URI changes (maybe by comparing body hashes?)
|
8
7
|
* Filters (e.g. skip entries matching a pattern)
|
@@ -11,3 +10,7 @@
|
|
11
10
|
* Profiles (support many feed lists and recipients)
|
12
11
|
* Send email notifications to user (e.g. when a feed is not available anymore)
|
13
12
|
* Plugin architecture
|
13
|
+
* Integrate with Mail gem for email sending
|
14
|
+
* Do not consider fetched if there was an error
|
15
|
+
* begin ensure end
|
16
|
+
* Fix sleeping
|
data/bin/feed2email
CHANGED
@@ -3,4 +3,9 @@
|
|
3
3
|
require 'feed2email'
|
4
4
|
require 'feed2email/feed'
|
5
5
|
|
6
|
-
|
6
|
+
if File.new('/tmp/feed2email.lock', 'w').flock(File::LOCK_NB | File::LOCK_EX)
|
7
|
+
Feed2Email::Feed.process_all
|
8
|
+
else
|
9
|
+
$stderr.puts 'An instance of feed2email is already running. Exiting...'
|
10
|
+
exit 1
|
11
|
+
end
|
data/lib/feed2email/config.rb
CHANGED
@@ -87,13 +87,15 @@ module Feed2Email
|
|
87
87
|
|
88
88
|
def defaults
|
89
89
|
{
|
90
|
-
'log_level'
|
91
|
-
'log_path'
|
92
|
-
'
|
93
|
-
'
|
94
|
-
'
|
95
|
-
'
|
96
|
-
'
|
90
|
+
'log_level' => 'info',
|
91
|
+
'log_path' => true,
|
92
|
+
'log_shift_age' => 0,
|
93
|
+
'log_shift_size' => 1, # megabyte
|
94
|
+
'max_entries' => 20,
|
95
|
+
'send_delay' => 10,
|
96
|
+
'sendmail_path' => '/usr/sbin/sendmail',
|
97
|
+
'smtp_auth' => 'login',
|
98
|
+
'smtp_starttls' => true,
|
97
99
|
}
|
98
100
|
end
|
99
101
|
|
data/lib/feed2email/core_ext.rb
CHANGED
data/lib/feed2email/entry.rb
CHANGED
data/lib/feed2email/feed.rb
CHANGED
@@ -16,31 +16,34 @@ module Feed2Email
|
|
16
16
|
class Feed
|
17
17
|
extend Forwardable
|
18
18
|
|
19
|
-
|
20
|
-
extend Forwardable
|
19
|
+
def self.feed_uris; @feed_uris end
|
21
20
|
|
22
|
-
|
21
|
+
def self.logger
|
22
|
+
Feed2Email.logger # delegate
|
23
23
|
end
|
24
24
|
|
25
|
+
def self.smtp_connection
|
26
|
+
Feed2Email.smtp_connection # delegate
|
27
|
+
end
|
28
|
+
|
29
|
+
logger.debug 'Loading feed subscriptions...'
|
30
|
+
@feed_uris = Feeds.new(File.join(CONFIG_DIR, 'feeds.yml'))
|
31
|
+
logger.info "Subscribed to #{'feed'.pluralize(feed_uris.size)}"
|
32
|
+
|
25
33
|
def self.process_all
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
34
|
+
begin
|
35
|
+
feed_uris.each_with_index do |uri, i|
|
36
|
+
feed = new(uri)
|
37
|
+
feed.process
|
38
|
+
feed_uris[i] = feed.uri # persist possible permanent redirect
|
39
|
+
end
|
40
|
+
ensure
|
41
|
+
smtp_connection.finalize
|
30
42
|
end
|
31
43
|
|
32
44
|
feed_uris.sync
|
33
45
|
end
|
34
46
|
|
35
|
-
def self.feed_uris
|
36
|
-
return @feed_uris if @feed_uris
|
37
|
-
|
38
|
-
log :debug, 'Loading feed subscriptions...'
|
39
|
-
@feed_uris = Feeds.new(File.join(CONFIG_DIR, 'feeds.yml'))
|
40
|
-
log :info, "Subscribed to #{'feed'.pluralize(feed_uris.size)}"
|
41
|
-
@feed_uris
|
42
|
-
end
|
43
|
-
|
44
47
|
attr_reader :uri
|
45
48
|
|
46
49
|
def initialize(uri)
|
@@ -48,7 +51,7 @@ module Feed2Email
|
|
48
51
|
end
|
49
52
|
|
50
53
|
def process
|
51
|
-
|
54
|
+
logger.info "Processing feed #{uri} ..."
|
52
55
|
|
53
56
|
return unless fetch_and_parse_feed
|
54
57
|
|
@@ -57,14 +60,14 @@ module Feed2Email
|
|
57
60
|
history.sync
|
58
61
|
meta.sync
|
59
62
|
else
|
60
|
-
|
63
|
+
logger.warn 'Feed does not have entries'
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
64
67
|
private
|
65
68
|
|
66
69
|
def fetch_feed
|
67
|
-
|
70
|
+
logger.debug 'Fetching feed...'
|
68
71
|
|
69
72
|
begin
|
70
73
|
handle_permanent_redirection
|
@@ -82,13 +85,13 @@ module Feed2Email
|
|
82
85
|
end
|
83
86
|
rescue OpenURI::HTTPError => e
|
84
87
|
if e.message == '304 Not Modified'
|
85
|
-
|
88
|
+
logger.info 'Feed not modified; skipping...'
|
86
89
|
return false
|
87
90
|
end
|
88
91
|
|
89
92
|
raise
|
90
93
|
rescue => e
|
91
|
-
|
94
|
+
logger.error 'Failed to fetch feed'
|
92
95
|
log_exception(e)
|
93
96
|
return false
|
94
97
|
end
|
@@ -102,7 +105,8 @@ module Feed2Email
|
|
102
105
|
|
103
106
|
if response.code == '301' && response['location'] =~ %r{\Ahttps?://}
|
104
107
|
self.uri = response['location']
|
105
|
-
|
108
|
+
logger.warn(
|
109
|
+
"Got permanently redirected! Updated feed location to #{uri}")
|
106
110
|
end
|
107
111
|
end
|
108
112
|
|
@@ -139,12 +143,12 @@ module Feed2Email
|
|
139
143
|
end
|
140
144
|
|
141
145
|
def parse_feed(xml_data)
|
142
|
-
|
146
|
+
logger.debug 'Parsing feed...'
|
143
147
|
|
144
148
|
begin
|
145
149
|
Feedzirra::Feed.parse(xml_data)
|
146
150
|
rescue => e
|
147
|
-
|
151
|
+
logger.error 'Failed to parse feed'
|
148
152
|
log_exception(e)
|
149
153
|
return false
|
150
154
|
end
|
@@ -170,8 +174,8 @@ module Feed2Email
|
|
170
174
|
}
|
171
175
|
end
|
172
176
|
|
173
|
-
def
|
174
|
-
Feed2Email
|
177
|
+
def logger
|
178
|
+
Feed2Email.logger # delegate
|
175
179
|
end
|
176
180
|
|
177
181
|
def max_entries
|
@@ -179,25 +183,25 @@ module Feed2Email
|
|
179
183
|
end
|
180
184
|
|
181
185
|
def process_entries
|
182
|
-
|
186
|
+
logger.info "Processing #{'entry'.pluralize(entries.size, 'entries')}..."
|
183
187
|
entries.each {|entry| process_entry(entry) }
|
184
188
|
end
|
185
189
|
|
186
190
|
def process_entry(entry)
|
187
|
-
|
191
|
+
logger.info "Processing entry #{entry.uri} ..."
|
188
192
|
|
189
193
|
if history.any?
|
190
194
|
if history.include?(entry.uri)
|
191
|
-
|
195
|
+
logger.debug 'Skipping old entry...'
|
192
196
|
else
|
193
197
|
# Sleep between entry processing to avoid Net::SMTPServerBusy errors
|
194
198
|
if config['send_delay'] > 0
|
195
|
-
|
196
|
-
"Sleeping for #{'second'.pluralize(config['send_delay'])}"
|
199
|
+
logger.debug(
|
200
|
+
"Sleeping for #{'second'.pluralize(config['send_delay'])}")
|
197
201
|
sleep(config['send_delay'])
|
198
202
|
end
|
199
203
|
|
200
|
-
|
204
|
+
logger.debug 'Sending new entry...'
|
201
205
|
|
202
206
|
begin
|
203
207
|
entry.send_mail
|
@@ -212,7 +216,7 @@ module Feed2Email
|
|
212
216
|
e = nil
|
213
217
|
end
|
214
218
|
else
|
215
|
-
|
219
|
+
logger.debug 'Skipping new feed entry...'
|
216
220
|
history << entry.uri
|
217
221
|
end
|
218
222
|
end
|
@@ -226,8 +230,8 @@ module Feed2Email
|
|
226
230
|
end
|
227
231
|
|
228
232
|
def log_exception(error)
|
229
|
-
|
230
|
-
error.backtrace.each {|line|
|
233
|
+
logger.error "#{error.class}: #{error.message.strip}"
|
234
|
+
error.backtrace.each {|line| logger.debug line }
|
231
235
|
end
|
232
236
|
|
233
237
|
def_delegator :data, :title, :title
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
|
3
|
+
module Feed2Email
|
4
|
+
class LazySMTPConnection
|
5
|
+
def config
|
6
|
+
Feed2Email.config # delegate
|
7
|
+
end
|
8
|
+
|
9
|
+
def connect
|
10
|
+
smtp.start('localhost', config['smtp_user'], config['smtp_pass'],
|
11
|
+
config['smtp_auth'].to_sym)
|
12
|
+
end
|
13
|
+
|
14
|
+
def connected?
|
15
|
+
smtp.started?
|
16
|
+
end
|
17
|
+
|
18
|
+
def finalize
|
19
|
+
smtp.finish if connected?
|
20
|
+
end
|
21
|
+
|
22
|
+
def send_message(*args)
|
23
|
+
connect unless connected?
|
24
|
+
smtp.send_message(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def smtp
|
28
|
+
return @smtp if @smtp
|
29
|
+
@smtp = Net::SMTP.new(config['smtp_host'], config['smtp_port'])
|
30
|
+
@smtp.enable_starttls if config['smtp_starttls']
|
31
|
+
@smtp
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/feed2email/logger.rb
CHANGED
@@ -1,42 +1,25 @@
|
|
1
1
|
require 'logger'
|
2
|
+
require 'feed2email/core_ext'
|
2
3
|
|
3
4
|
module Feed2Email
|
4
5
|
class Logger
|
5
|
-
|
6
|
-
@log_path = log_path
|
7
|
-
@log_level = log_level
|
8
|
-
end
|
6
|
+
attr_reader :logger
|
9
7
|
|
10
|
-
def
|
11
|
-
|
8
|
+
def initialize(log_path, log_level, log_shift_age, log_shift_size)
|
9
|
+
@log_path = log_path
|
10
|
+
@logger = ::Logger.new(log_to(log_path), log_shift_age,
|
11
|
+
log_shift_size.megabytes)
|
12
|
+
@logger.level = ::Logger.const_get(log_level.upcase)
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
15
16
|
|
16
|
-
def log_to
|
17
|
+
def log_to(log_path)
|
17
18
|
if log_path == true
|
18
19
|
$stdout
|
19
20
|
elsif log_path # truthy but not true (a path)
|
20
21
|
File.expand_path(log_path)
|
21
22
|
end
|
22
23
|
end
|
23
|
-
|
24
|
-
def logger
|
25
|
-
return @logger if @logger
|
26
|
-
|
27
|
-
@logger = ::Logger.new(log_to)
|
28
|
-
|
29
|
-
if log_level
|
30
|
-
@logger.level = ::Logger.const_get(log_level.upcase)
|
31
|
-
else
|
32
|
-
@logger.level = ::Logger::INFO
|
33
|
-
end
|
34
|
-
|
35
|
-
@logger
|
36
|
-
end
|
37
|
-
|
38
|
-
def log_path; @log_path end
|
39
|
-
|
40
|
-
def log_level; @log_level end
|
41
24
|
end
|
42
25
|
end
|
data/lib/feed2email/mail.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'mail'
|
2
|
-
require '
|
2
|
+
require 'feed2email/version'
|
3
3
|
|
4
4
|
module Feed2Email
|
5
5
|
class Mail
|
@@ -24,6 +24,7 @@ module Feed2Email
|
|
24
24
|
<body>
|
25
25
|
<h1><a href="%{uri}">%{title}</a></h1>
|
26
26
|
%{content}
|
27
|
+
<p>%{published}</p>
|
27
28
|
<p><a href="%{uri}">%{uri}</a></p>
|
28
29
|
<p>--<br>
|
29
30
|
Sent by <a href="https://github.com/agorf/feed2email">feed2email
|
@@ -31,38 +32,30 @@ module Feed2Email
|
|
31
32
|
</body>
|
32
33
|
</html>
|
33
34
|
}.gsub(/^\s+/, '') % {
|
34
|
-
content:
|
35
|
-
|
36
|
-
|
35
|
+
content: entry.content,
|
36
|
+
published: published,
|
37
|
+
title: entry.title.strip_html,
|
38
|
+
uri: entry.uri.escape_html,
|
37
39
|
}
|
38
40
|
end
|
39
41
|
|
40
42
|
def body_text
|
41
|
-
|
42
|
-
# [%{title}](%{uri})
|
43
|
-
|
44
|
-
%{content}
|
45
|
-
|
46
|
-
%{uri}
|
47
|
-
|
48
|
-
--
|
49
|
-
Sent by feed2email #{VERSION} at #{Time.now}
|
50
|
-
}.gsub(/^\s+/, '') % {
|
51
|
-
content: @entry.content.to_markdown,
|
52
|
-
title: @entry.title.strip_html,
|
53
|
-
uri: @entry.uri,
|
54
|
-
}
|
43
|
+
body_html.to_markdown
|
55
44
|
end
|
56
45
|
|
57
46
|
def config
|
58
47
|
Feed2Email.config # delegate
|
59
48
|
end
|
60
49
|
|
50
|
+
def entry; @entry end
|
51
|
+
|
52
|
+
def feed_title; @feed_title end
|
53
|
+
|
61
54
|
def mail
|
62
55
|
::Mail.new.tap do |m|
|
63
|
-
m.from = %{"#{
|
56
|
+
m.from = %{"#{feed_title}" <#{config['sender']}>}
|
64
57
|
m.to = config['recipient']
|
65
|
-
m.subject =
|
58
|
+
m.subject = entry.title.strip_html
|
66
59
|
m.html_part = mail_part('text/html', body_html)
|
67
60
|
m.text_part = mail_part('text/plain', body_text)
|
68
61
|
end.to_s
|
@@ -75,6 +68,14 @@ module Feed2Email
|
|
75
68
|
part
|
76
69
|
end
|
77
70
|
|
71
|
+
def published
|
72
|
+
return nil unless entry.author || entry.published
|
73
|
+
text = 'Published'
|
74
|
+
text << " by #{entry.author}" if entry.author
|
75
|
+
text << " at #{entry.published}" if entry.published
|
76
|
+
text
|
77
|
+
end
|
78
|
+
|
78
79
|
def send_with_sendmail
|
79
80
|
open("|#{config['sendmail_path']} #{config['recipient']}", 'w') do |f|
|
80
81
|
f.write(mail)
|
@@ -82,17 +83,7 @@ module Feed2Email
|
|
82
83
|
end
|
83
84
|
|
84
85
|
def send_with_smtp
|
85
|
-
|
86
|
-
smtp.enable_starttls if config['smtp_tls']
|
87
|
-
|
88
|
-
smtp.start(
|
89
|
-
'localhost',
|
90
|
-
config['smtp_user'],
|
91
|
-
config['smtp_pass'],
|
92
|
-
config['smtp_auth'].to_sym
|
93
|
-
) do
|
94
|
-
smtp.send_message(mail, config['sender'], config['recipient'])
|
95
|
-
end
|
86
|
+
smtp_connection.send_message(mail, config['sender'], config['recipient'])
|
96
87
|
end
|
97
88
|
|
98
89
|
def smtp_configured?
|
@@ -101,5 +92,9 @@ module Feed2Email
|
|
101
92
|
config['smtp_user'] &&
|
102
93
|
config['smtp_pass']
|
103
94
|
end
|
95
|
+
|
96
|
+
def smtp_connection
|
97
|
+
Feed2Email.smtp_connection
|
98
|
+
end
|
104
99
|
end
|
105
100
|
end
|
data/lib/feed2email/version.rb
CHANGED
data/lib/feed2email.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
|
+
require 'feed2email/config'
|
2
|
+
require 'feed2email/lazy_smtp_connection'
|
3
|
+
require 'feed2email/logger'
|
4
|
+
|
1
5
|
module Feed2Email
|
2
6
|
CONFIG_DIR = File.expand_path('~/.feed2email')
|
3
7
|
|
4
|
-
def self.config
|
5
|
-
@config ||= Config.new(File.join(CONFIG_DIR, 'config.yml'))
|
6
|
-
end
|
8
|
+
def self.config; @config end
|
7
9
|
|
8
10
|
def self.logger
|
9
|
-
@logger
|
11
|
+
@logger.logger # delegate
|
10
12
|
end
|
11
13
|
|
12
|
-
def self.
|
13
|
-
logger.log(*args) # delegate
|
14
|
-
end
|
15
|
-
end
|
14
|
+
def self.smtp_connection; @smtp_connection end
|
16
15
|
|
17
|
-
|
18
|
-
|
16
|
+
@config = Config.new(File.join(CONFIG_DIR, 'config.yml'))
|
17
|
+
|
18
|
+
@logger = Logger.new(config['log_path'], config['log_level'],
|
19
|
+
config['log_shift_age'], config['log_shift_size'])
|
20
|
+
|
21
|
+
@smtp_connection = LazySMTPConnection.new
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feed2email
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aggelos Orfanakos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: feedzirra
|
@@ -159,6 +159,7 @@ files:
|
|
159
159
|
- lib/feed2email/feed_history.rb
|
160
160
|
- lib/feed2email/feed_meta.rb
|
161
161
|
- lib/feed2email/feeds.rb
|
162
|
+
- lib/feed2email/lazy_smtp_connection.rb
|
162
163
|
- lib/feed2email/logger.rb
|
163
164
|
- lib/feed2email/mail.rb
|
164
165
|
- lib/feed2email/version.rb
|