attachments 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
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,71 @@
1
+ = attachments
2
+
3
+ Extract mail parts of specified mime types.
4
+
5
+ == DESCRIPTION
6
+
7
+ It's original intention is as a helper class class for filtering
8
+ email attachments before forwarding. The extracted attachments
9
+ are saved in the /tmp directory.
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ Is the /tmp directory and the 'file' shell command on your OS? If not
14
+ some porting work is needed.
15
+
16
+ == REQUIREMENTS:
17
+
18
+ Typedown is presently using the mail and uuidtools ruby gems.
19
+ It uses the 'file' shell command from filemagic to decide mime types
20
+ when they are uncertain.
21
+
22
+
23
+ == SYNOPSIS:
24
+
25
+ require 'rubygems'
26
+ require 'attachments'
27
+
28
+
29
+ # Which mime types do you want to accept?
30
+ extract = Attachments::Extract.new [ "text/plain" ]
31
+
32
+ # I make postfix save incoming mails in MailDir,
33
+ # then glob that directory
34
+ INCOMING_MAIL_DIR = "/your/MailDir"
35
+ mailfiles = Dir.glob(INCOMING_MAIL_DIR + "/*")
36
+
37
+ # Process the mails
38
+ mailfiles.each do |m|
39
+ # Open mail stored in filename
40
+ extract.parse m
41
+ # Traverse through the extracted attachments
42
+ extract.files.each do |f|
43
+ # Do something with the attachments
44
+ puts f.inspect
45
+ case f[:mime_type]
46
+ when "text/plain" then
47
+ puts File.read(f[:tmpfile])
48
+ end
49
+ end
50
+ # Remove tmp files and prepare for new parsing action
51
+ extract.close
52
+
53
+ # Probably you want to delete or move the processed email
54
+ # to an archive here
55
+ # FileUtils::rm(m)
56
+ end
57
+
58
+
59
+ == Note on Patches/Pull Requests
60
+
61
+ * Fork the project.
62
+ * Make your feature addition or bug fix.
63
+ * Add tests for it. This is important so I don't break it in a
64
+ future version unintentionally.
65
+ * Commit, do not mess with rakefile, version, or history.
66
+ (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)
67
+ * Send me a pull request. Bonus points for topic branches.
68
+
69
+ == Copyright
70
+
71
+ 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 = "attachments"
8
+ gem.summary = %Q{Extract mail parts of specified mime types.}
9
+ gem.description = %Q{It's original intention is as a helper class class for filtering email attachments before forwarding. The extracted attachments are saved in the /tmp directory.}
10
+ gem.email = "rune@epubify.com"
11
+ gem.homepage = "http://github.com/wrimle/attachments"
12
+ gem.authors = ["Rune Myrland"]
13
+ gem.add_dependency('mail','>= 2.2.5')
14
+ gem.add_dependency('uuidtools','>= 2.1.1')
15
+ #gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
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 = "attachments #{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
@@ -0,0 +1,121 @@
1
+ require 'rubygems'
2
+ require 'uuidtools'
3
+ require 'mail'
4
+
5
+
6
+ module Attachments
7
+ module Error
8
+ class Base < StandardError; end
9
+ class SaveFailed < Base; end
10
+ end
11
+
12
+
13
+ # Extract attachments of specific types from emails and save them in files
14
+ class Extract
15
+ UNCERTAIN_TYPES = [ "application/octet-stream" ].to_set
16
+
17
+ def initialize include_types = [ "text/plain" ]
18
+ @include_types = include_types
19
+ reset
20
+ end
21
+
22
+ def close
23
+ files.each do |f|
24
+ FileUtils::rm(f[:filename])
25
+ end
26
+ reset
27
+ end
28
+
29
+ def parse filename
30
+ @last_parsed = filename
31
+
32
+ # Load the email
33
+ mail = Mail.read(filename)
34
+
35
+ # To and from is important when sending mail to db
36
+ @to = mail.to
37
+
38
+ @from = mail.from
39
+
40
+ # Parse parts recursively until it is not multipart
41
+ # Ignore types that are not suited for forwarding
42
+ parse_part mail
43
+ end
44
+
45
+ def to
46
+ @to || nil
47
+ end
48
+
49
+ def from
50
+ @from || nil
51
+ end
52
+
53
+ def name
54
+ @name
55
+ end
56
+
57
+ def files
58
+ @files
59
+ end
60
+
61
+ def last_parsed
62
+ @last_parsed
63
+ end
64
+
65
+
66
+ private
67
+ # Use close
68
+ def reset
69
+ @last_parsed = nil
70
+ @to = nil
71
+ @name = nil
72
+ @from = nil
73
+ @files = []
74
+ end
75
+
76
+ def parse_part mail
77
+ # Filter parts with a type that is not of interest
78
+ ct = mail.content_type.split(/;/, 2)[0] if mail.content_type
79
+ unless(mail.multipart? || (ct && @include_types.include?(ct)))
80
+ return
81
+ end
82
+
83
+ # If part is multipart, recurse
84
+ if mail.multipart?
85
+ mail.parts.each do |p|
86
+ parse_part p
87
+ end
88
+ else
89
+ # Grab filename from content parameters, and make sure its sane
90
+ @name = mail.content_type_parameters['name'] || "unnamed"
91
+ @name.gsub! /[^\w\.\-]/, '_' # Sanitize
92
+
93
+ # Make it unique
94
+ uuid = UUIDTools::UUID.random_create.hexdigest
95
+
96
+ # The filename used for storage
97
+ filename = "#{@name}.#{uuid}"
98
+ filepath = "/tmp/#{filename}"
99
+
100
+ # Save part as it is of a supported type
101
+ f = File.new(filepath, "wb")
102
+ f.write(mail.body.decoded)
103
+ f.close
104
+
105
+ unless File.exists?(filepath)
106
+ raise Error::SaveFailed, "Save failed for ", filepath, "\n"
107
+ return
108
+ end
109
+
110
+ # Sort out the mime type
111
+ mime_type = ct
112
+ if(UNCERTAIN_TYPES.include? mime_type)
113
+ mime_type = FileMagic::mime filename
114
+ end
115
+
116
+ # Save meta-data for further processing
117
+ @files << { :name => @name, :tmpfile => filepath, :save_as => name, :upload_to => filename, :mime_type => mime_type, :from => @from, :to => @to }
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,6 @@
1
+
2
+ class FileMagic
3
+ def self.mime filename
4
+ mime_type = `file --brief --mime-type #{filename}`.strip()
5
+ end
6
+ end
@@ -0,0 +1,2 @@
1
+ require 'attachments/extract.rb'
2
+ require 'attachments/filemagic.rb'
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'attachments'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestAttachments < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: attachments
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Rune Myrland
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-13 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mail
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 2
32
+ - 2
33
+ - 5
34
+ version: 2.2.5
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: uuidtools
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 9
46
+ segments:
47
+ - 2
48
+ - 1
49
+ - 1
50
+ version: 2.1.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: It's original intention is as a helper class class for filtering email attachments before forwarding. The extracted attachments are saved in the /tmp directory.
54
+ email: rune@epubify.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files:
60
+ - LICENSE
61
+ - README.rdoc
62
+ files:
63
+ - .document
64
+ - .gitignore
65
+ - LICENSE
66
+ - README.rdoc
67
+ - Rakefile
68
+ - VERSION
69
+ - lib/attachments.rb
70
+ - lib/attachments/extract.rb
71
+ - lib/attachments/filemagic.rb
72
+ - test/helper.rb
73
+ - test/test_attachments.rb
74
+ has_rdoc: true
75
+ homepage: http://github.com/wrimle/attachments
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options:
80
+ - --charset=UTF-8
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ requirements: []
102
+
103
+ rubyforge_project:
104
+ rubygems_version: 1.3.7
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Extract mail parts of specified mime types.
108
+ test_files:
109
+ - test/test_attachments.rb
110
+ - test/helper.rb