typedown2blog 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +52 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/bin/blog +27 -0
- data/bin/control_typedown2blog_batcher.rb +6 -0
- data/bin/typedown2blog_batcher +40 -0
- data/lib/typedown2blog.rb +5 -0
- data/lib/typedown2blog/blog.rb +41 -0
- data/lib/typedown2blog/parse_mail.rb +74 -0
- data/lib/typedown2blog/spec.rb +35 -0
- data/test/data/mail_0001.eml +48 -0
- data/test/data/mail_0002.eml +1255 -0
- data/test/data/mail_0002.jpg +0 -0
- data/test/data/mail_0003.eml +47 -0
- data/test/helper.rb +10 -0
- data/test/test_typedown2blog.rb +47 -0
- metadata +134 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Rune Myrland
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
= typedown2blog
|
2
|
+
|
3
|
+
An email gateway for forwarding typedown formatted mail to blogs, via
|
4
|
+
Mail2Blog interfaces. Designed to read mails from a MailDir directory.
|
5
|
+
|
6
|
+
== FEATURES/PROBLEMS:
|
7
|
+
|
8
|
+
IMPORTANT: The server daemon/batcher "typedown2blog_batcher" will delete
|
9
|
+
emails once processed. If you don't want this behaviour you can easily create
|
10
|
+
your own version of the script. You have to move the mail out of the
|
11
|
+
watched directory though, or the mail will be reprocessed every 3 seconds.
|
12
|
+
|
13
|
+
== USAGE
|
14
|
+
|
15
|
+
To use the bin/blog or bin/typedown2blog_batcher create blog_config.rb
|
16
|
+
in your ruby path, with content similar to:
|
17
|
+
|
18
|
+
|
19
|
+
Typedown2Blog::Spec::setup do
|
20
|
+
blog do
|
21
|
+
email 'blog@example.com'
|
22
|
+
end
|
23
|
+
|
24
|
+
mail_defaults do
|
25
|
+
delivery_method :smtp, {
|
26
|
+
:address => 'your_mail_server',
|
27
|
+
:port => 25,
|
28
|
+
:domain => 'example.com',
|
29
|
+
:user_name => 'you@example.com',
|
30
|
+
:password => 'your_password',
|
31
|
+
:authentication => :plain,
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
# Only used by bin/typedown2blog_batcher
|
36
|
+
glob "your_home/Maildir/new/*"
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
== Note on Patches/Pull Requests
|
41
|
+
|
42
|
+
* Fork the project.
|
43
|
+
* Make your feature addition or bug fix.
|
44
|
+
* Add tests for it. This is important so I don't break it in a
|
45
|
+
future version unintentionally.
|
46
|
+
* Commit, do not mess with rakefile, version, or history.
|
47
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
48
|
+
* Send me a pull request. Bonus points for topic branches.
|
49
|
+
|
50
|
+
== Copyright
|
51
|
+
|
52
|
+
Copyright (c) 2010 Rune Myrland. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "typedown2blog"
|
8
|
+
gem.summary = %Q{Email gateway for reformatting typedown documents before forwarding to blog}
|
9
|
+
gem.description = %Q{The script will forward to the blog via a Mail2Blog interface.}
|
10
|
+
gem.email = "rune@epubify.com"
|
11
|
+
gem.homepage = "http://github.com/wrimle/typedown2blog"
|
12
|
+
gem.authors = ["Rune Myrland"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
gem.add_dependency('attachments','>= 0.0.7')
|
15
|
+
gem.add_dependency('typedown','>= 0.0.3')
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'lib' << 'test'
|
26
|
+
test.pattern = 'test/**/test_*.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/**/test_*.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rcov do
|
39
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
task :test => :check_dependencies
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "typedown2blog #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/bin/blog
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'rubygems'
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'typedown2blog'
|
8
|
+
|
9
|
+
include Typedown2Blog
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'blog_config'
|
13
|
+
rescue MissingSourceFile => err
|
14
|
+
puts "Put your mail settings in blog_config.rb"
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
unless Typedown2Blog::Blog.email
|
20
|
+
puts "#{__FILE__} blog_email incoming_mails_glob"
|
21
|
+
puts "Or specify in blog_config.rb"
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
|
25
|
+
ARGV.each do |filename|
|
26
|
+
Blog.post filename
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
require 'rubygems'
|
7
|
+
require 'typedown2blog'
|
8
|
+
|
9
|
+
include Typedown2Blog
|
10
|
+
|
11
|
+
|
12
|
+
begin
|
13
|
+
require 'blog_config'
|
14
|
+
rescue MissingSourceFile => err
|
15
|
+
puts "Put your settings in blog_config.rb"
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
puts Typedown2Blog::Blog.email
|
20
|
+
puts Typedown2Blog::Spec.glob
|
21
|
+
|
22
|
+
unless Typedown2Blog::Blog.email && Typedown2Blog::Spec.glob
|
23
|
+
puts "#{__FILE__} blog_email incoming_mails_glob"
|
24
|
+
puts "Or specify in blog_config.rb"
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
loop do
|
30
|
+
# Read maildir and parse them if they are there
|
31
|
+
didWork = false
|
32
|
+
Dir.glob(Spec::glob) do |filename|
|
33
|
+
Blog.post filename
|
34
|
+
FileUtils::rm(filename)
|
35
|
+
didWork = true
|
36
|
+
end
|
37
|
+
|
38
|
+
# If no mails where found, sleep a bit before looking again
|
39
|
+
sleep(3) unless didWork
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Typedown2Blog
|
4
|
+
class Blog
|
5
|
+
begin
|
6
|
+
@email = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
def self.setup &block
|
11
|
+
instance_eval &block
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def self.email v = nil
|
16
|
+
if v
|
17
|
+
@email = v
|
18
|
+
else
|
19
|
+
@email
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def self.email= v
|
25
|
+
@email = v
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def self.post filename
|
30
|
+
mail_to = @email
|
31
|
+
mail = Typedown2Blog::parse_mail filename do
|
32
|
+
to mail_to
|
33
|
+
|
34
|
+
typedown = text_part.body.decoded
|
35
|
+
typedown_root = Typedown::Section.sectionize(typedown, subject)
|
36
|
+
text_part.body = "#{typedown_root.body.to_html}\n\n"
|
37
|
+
end
|
38
|
+
mail.deliver!
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'attachments'
|
4
|
+
require 'typedown'
|
5
|
+
|
6
|
+
module Typedown2Blog
|
7
|
+
|
8
|
+
def parse_mail filename, &block
|
9
|
+
out = nil
|
10
|
+
extract = Attachments::Extract.new [ "image/jpeg" ]
|
11
|
+
begin
|
12
|
+
out = Mail.new do
|
13
|
+
extract.parse filename
|
14
|
+
from extract.from
|
15
|
+
|
16
|
+
typedown_root = Typedown::Section.sectionize(extract.text_body, extract.subject)
|
17
|
+
|
18
|
+
subject typedown_root.title
|
19
|
+
text_part do
|
20
|
+
charset = 'UTF-8'
|
21
|
+
body typedown_root.body
|
22
|
+
end
|
23
|
+
|
24
|
+
extract.files.each do |f|
|
25
|
+
file = File.new(f[:tmpfile], "rb")
|
26
|
+
data = file.read()
|
27
|
+
file.close()
|
28
|
+
|
29
|
+
add_file(:filename => f[:save_as], :content => data )
|
30
|
+
attachments[f[:save_as]][:mime_type] = f[:mime_type]
|
31
|
+
|
32
|
+
#convert_to_multipart unless self.multipart?
|
33
|
+
#add_multipart_mixed_header
|
34
|
+
#attachments[f[:save_as]] = {
|
35
|
+
# :mime_type => f[:mime_type],
|
36
|
+
# :content => data,
|
37
|
+
#}
|
38
|
+
end
|
39
|
+
|
40
|
+
if block_given?
|
41
|
+
instance_eval &block
|
42
|
+
end
|
43
|
+
end
|
44
|
+
ensure
|
45
|
+
extract.close
|
46
|
+
end
|
47
|
+
out
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def send_to_blog filename, secret_mail
|
52
|
+
mail = Typedown2Blog::parse_mail filename do
|
53
|
+
to secret_mail
|
54
|
+
|
55
|
+
typedown = text_part.body.decoded
|
56
|
+
typedown_root = Typedown::Section.sectionize(typedown, subject)
|
57
|
+
text_part.body = "#{typedown_root.body.to_html}\n\n"
|
58
|
+
end
|
59
|
+
mail.deliver!
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
def parse_glob glob_name, &block
|
65
|
+
didWork = false
|
66
|
+
Dir.glob(glob_name) do |filename|
|
67
|
+
block.call filename
|
68
|
+
didWork = true
|
69
|
+
end
|
70
|
+
|
71
|
+
didWork
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
module Typedown2Blog
|
5
|
+
class Spec
|
6
|
+
begin
|
7
|
+
@glob = ARGV[0] || ENV['TYPEDOWN_MAIL_GLOB']
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def self.setup &block
|
12
|
+
instance_eval &block
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def self.blog &block
|
17
|
+
Blog.setup &block
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def self.mail_defaults &block
|
22
|
+
Mail.defaults &block
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def self.glob v = nil
|
27
|
+
if v
|
28
|
+
@glob = v
|
29
|
+
else
|
30
|
+
@glob
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Return-Path: <rune@epubify.com>
|
2
|
+
X-Original-To: posterous@boox.epubify.com
|
3
|
+
Delivered-To: posterous@boox.epubify.com
|
4
|
+
Received: from mail-gw0-f51.google.com (mail-gw0-f51.google.com [74.125.83.51])
|
5
|
+
by boox (Postfix) with ESMTP id 053CEA8805
|
6
|
+
for <posterous@boox.epubify.com>; Fri, 13 Aug 2010 11:53:59 +0000 (UTC)
|
7
|
+
Received: by gwb17 with SMTP id 17so702822gwb.38
|
8
|
+
for <posterous@boox.epubify.com>; Fri, 13 Aug 2010 04:53:40 -0700 (PDT)
|
9
|
+
MIME-Version: 1.0
|
10
|
+
Received: by 10.151.111.1 with SMTP id o1mr1964300ybm.26.1281700420730; Fri,
|
11
|
+
13 Aug 2010 04:53:40 -0700 (PDT)
|
12
|
+
Received: by 10.150.217.13 with HTTP; Fri, 13 Aug 2010 04:53:40 -0700 (PDT)
|
13
|
+
X-Originating-IP: [84.208.65.71]
|
14
|
+
Date: Fri, 13 Aug 2010 13:53:40 +0200
|
15
|
+
Message-ID: <AANLkTimsuBB4r-9rEW3iUd49hb1EnEyX58+eyxqQyeFs@mail.gmail.com>
|
16
|
+
Subject: Test
|
17
|
+
From: Rune Myrland <rune@epubify.com>
|
18
|
+
To: posterous@boox.epubify.com
|
19
|
+
Content-Type: multipart/alternative; boundary=001517576834493df4048db32256
|
20
|
+
|
21
|
+
--001517576834493df4048db32256
|
22
|
+
Content-Type: text/plain; charset=ISO-8859-1
|
23
|
+
Content-Transfer-Encoding: quoted-printable
|
24
|
+
|
25
|
+
! Overskrift
|
26
|
+
|
27
|
+
Litt test.
|
28
|
+
|
29
|
+
!! En underoverskrift.
|
30
|
+
|
31
|
+
Og s=E5
|
32
|
+
|
33
|
+
-. Si noe da!
|
34
|
+
|
35
|
+
-. Hva da?
|
36
|
+
|
37
|
+
-. Hva som helst?
|
38
|
+
|
39
|
+
--001517576834493df4048db32256
|
40
|
+
Content-Type: text/html; charset=ISO-8859-1
|
41
|
+
Content-Transfer-Encoding: quoted-printable
|
42
|
+
|
43
|
+
<div>! Overskrift<br></div><div><br></div><div>Litt test.</div><div><br></d=
|
44
|
+
iv><div>!! En underoverskrift.</div><div><br></div><div>Og s=E5</div><div><=
|
45
|
+
br></div><div>-. Si noe da!</div><div><br></div><div>-. Hva da?</div><div>
|
46
|
+
<br></div><div>-. Hva som helst?</div><div><br></div>
|
47
|
+
|
48
|
+
--001517576834493df4048db32256--
|