gmail 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +27 -27
  3. data/.rspec +1 -1
  4. data/.rubocop.yml +13 -13
  5. data/.rubocop_todo.yml +239 -239
  6. data/.travis.yml +19 -19
  7. data/CHANGELOG.md +145 -139
  8. data/Gemfile +3 -3
  9. data/LICENSE +21 -21
  10. data/README.md +355 -354
  11. data/Rakefile +46 -46
  12. data/gmail.gemspec +34 -34
  13. data/lib/gmail.rb +78 -78
  14. data/lib/gmail/client.rb +34 -34
  15. data/lib/gmail/client/base.rb +229 -229
  16. data/lib/gmail/client/plain.rb +24 -24
  17. data/lib/gmail/client/xoauth.rb +68 -68
  18. data/lib/gmail/client/xoauth2.rb +39 -39
  19. data/lib/gmail/imap_extensions.rb +159 -150
  20. data/lib/gmail/labels.rb +79 -79
  21. data/lib/gmail/mailbox.rb +175 -135
  22. data/lib/gmail/message.rb +207 -207
  23. data/lib/gmail/version.rb +3 -3
  24. data/spec/account.yml.example +1 -1
  25. data/spec/account.yml.obfus +2 -2
  26. data/spec/gmail/client/base_spec.rb +5 -5
  27. data/spec/gmail/client/plain_spec.rb +169 -168
  28. data/spec/gmail/client/xoauth2_spec.rb +186 -186
  29. data/spec/gmail/client/xoauth_spec.rb +5 -5
  30. data/spec/gmail/client_spec.rb +5 -5
  31. data/spec/gmail/imap_extensions_spec.rb +47 -12
  32. data/spec/gmail/labels_spec.rb +27 -18
  33. data/spec/gmail/mailbox_spec.rb +84 -47
  34. data/spec/gmail/message_spec.rb +181 -181
  35. data/spec/gmail_spec.rb +39 -39
  36. data/spec/recordings/gmail/_new_connects_with_client_and_give_it_context_when_block_given.yml +28 -28
  37. data/spec/recordings/gmail/_new_connects_with_gmail_service_and_return_valid_connection_object.yml +28 -28
  38. data/spec/recordings/gmail/_new_does_not_raise_error_when_couldn_t_connect_with_given_account.yml +13 -13
  39. data/spec/recordings/gmail/_new_raises_error_when_couldn_t_connect_with_given_account.yml +13 -13
  40. data/spec/recordings/gmail_client_plain/instance/_connection_automatically_logs_in_to_gmail_account_when_it_s_called.yml +42 -42
  41. data/spec/recordings/gmail_client_plain/instance/delivers_inline_composed_email.yml +42 -42
  42. data/spec/recordings/gmail_client_plain/instance/does_not_log_in_when_given_gmail_account_is_invalid.yml +13 -13
  43. data/spec/recordings/gmail_client_plain/instance/does_not_raise_error_even_though_gmail_account_is_invalid.yml +13 -13
  44. data/spec/recordings/gmail_client_plain/instance/labels/checks_if_there_is_given_label_defined.yml +196 -196
  45. data/spec/recordings/gmail_client_plain/instance/labels/creates_given_label.yml +151 -151
  46. data/spec/recordings/gmail_client_plain/instance/labels/removes_existing_label.yml +146 -146
  47. data/spec/recordings/gmail_client_plain/instance/labels/returns_list_of_all_available_labels.yml +113 -113
  48. data/spec/recordings/gmail_client_plain/instance/properly_logs_in_to_valid_gmail_account.yml +42 -42
  49. data/spec/recordings/gmail_client_plain/instance/properly_logs_out_from_gmail.yml +42 -42
  50. data/spec/recordings/gmail_client_plain/instance/properly_switches_to_given_mailbox.yml +109 -109
  51. data/spec/recordings/gmail_client_plain/instance/properly_switches_to_given_mailbox_using_block_style.yml +109 -109
  52. data/spec/recordings/gmail_client_plain/instance/raises_error_when_given_gmail_account_is_invalid_and_errors_enabled.yml +13 -13
  53. data/spec/recordings/gmail_client_xo_auth2/instance/does_not_log_in_when_given_gmail_account_is_invalid.yml +13 -13
  54. data/spec/recordings/gmail_client_xo_auth2/instance/labels/checks_if_there_is_given_label_defined.yml +27 -27
  55. data/spec/recordings/gmail_client_xo_auth2/instance/labels/creates_given_label.yml +39 -39
  56. data/spec/recordings/gmail_client_xo_auth2/instance/labels/removes_existing_label.yml +39 -39
  57. data/spec/recordings/gmail_client_xo_auth2/instance/labels/returns_list_of_all_available_labels.yml +27 -27
  58. data/spec/recordings/gmail_client_xo_auth2/instance/properly_logs_in_to_valid_gmail_account.yml +15 -15
  59. data/spec/recordings/gmail_client_xo_auth2/instance/properly_logs_out_from_gmail.yml +15 -15
  60. data/spec/recordings/gmail_client_xo_auth2/instance/properly_switches_to_given_mailbox.yml +40 -40
  61. data/spec/recordings/gmail_client_xo_auth2/instance/properly_switches_to_given_mailbox_using_block_style.yml +40 -40
  62. data/spec/recordings/gmail_client_xo_auth2/instance/raises_error_when_given_gmail_account_is_invalid_and_errors_enabled.yml +13 -13
  63. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/all/localizes_into_the_appropriate_label.yml +116 -116
  64. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/and_the_mailbox_does_not_exist/returns_the_mailbox_name_as_a_string.yml +110 -0
  65. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/drafts/localizes_into_the_appropriate_label.yml +116 -116
  66. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/flagged/localizes_into_the_appropriate_label.yml +116 -116
  67. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/important/localizes_into_the_appropriate_label.yml +116 -116
  68. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/inbox/localizes_into_the_appropriate_label.yml +42 -42
  69. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/junk/localizes_into_the_appropriate_label.yml +116 -116
  70. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/sent/localizes_into_the_appropriate_label.yml +116 -116
  71. data/spec/recordings/gmail_labels/localize/when_given_the_xl_is_tflag/trash/localizes_into_the_appropriate_label.yml +116 -116
  72. data/spec/recordings/gmail_mailbox/instance/counts_all_emails.yml +277 -277
  73. data/spec/recordings/gmail_mailbox/instance/finds_messages.yml +586 -586
  74. data/spec/recordings/gmail_mailbox/instance/waits_once.yml +136 -0
  75. data/spec/recordings/gmail_mailbox/instance/waits_repeatedly.yml +141 -0
  76. data/spec/recordings/gmail_mailbox/instance/waits_with_29-minute_re-issue.yml +136 -0
  77. data/spec/recordings/gmail_mailbox/instance/waits_with_an_unblocked_connection.yml +207 -0
  78. data/spec/recordings/gmail_mailbox/on_initialize/sets_client_and_name.yml +42 -42
  79. data/spec/recordings/gmail_mailbox/on_initialize/works_in_inbox_by_default.yml +42 -42
  80. data/spec/recordings/gmail_message/initialize/sets_prefetch_attrs.yml +578 -578
  81. data/spec/recordings/gmail_message/initialize/sets_uid_and_mailbox.yml +580 -580
  82. data/spec/recordings/gmail_message/instance_methods/deletes_itself.yml +637 -637
  83. data/spec/recordings/gmail_message/instance_methods/marks_itself_read.yml +682 -682
  84. data/spec/recordings/gmail_message/instance_methods/marks_itself_unread.yml +686 -686
  85. data/spec/recordings/gmail_message/instance_methods/moves_from_one_tag_to_other.yml +862 -862
  86. data/spec/recordings/gmail_message/instance_methods/removes_a_given_label.yml +776 -776
  87. data/spec/recordings/gmail_message/instance_methods/removes_a_given_label_with_old_method.yml +776 -776
  88. data/spec/recordings/gmail_message/instance_methods/sets_given_label.yml +690 -690
  89. data/spec/recordings/gmail_message/instance_methods/sets_given_label_with_old_method.yml +691 -691
  90. data/spec/spec_helper.rb +53 -53
  91. data/spec/support/imap_mock.rb +181 -129
  92. data/spec/support/obfuscation.rb +52 -52
  93. metadata +78 -5
data/Rakefile CHANGED
@@ -1,46 +1,46 @@
1
- #!/usr/bin/env rake
2
-
3
- begin
4
- require 'bundler/setup'
5
- rescue LoadError
6
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
- end
8
-
9
- begin
10
- require 'rdoc/task'
11
- rescue LoadError
12
- require 'rdoc/rdoc'
13
- require 'rake/rdoctask'
14
- RDoc::Task = Rake::RDocTask
15
- end
16
-
17
- RDoc::Task.new(:rdoc) do |rdoc|
18
- rdoc.rdoc_dir = 'rdoc'
19
- rdoc.title = "Gmail for Ruby #{Gmail::VERSION}"
20
- rdoc.rdoc_files.include('README*')
21
- rdoc.rdoc_files.include('lib/**/*.rb')
22
- end
23
-
24
- Bundler::GemHelper.install_tasks
25
-
26
- begin
27
- require 'rspec/core/rake_task'
28
- RSpec::Core::RakeTask.new(:spec)
29
- rescue LoadError
30
- task :spec do
31
- abort 'Run `gem install rspec` to install RSpec'
32
- end
33
- end
34
-
35
- task :default => :spec
36
-
37
- $LOAD_PATH.unshift(File.dirname(__FILE__))
38
- require 'spec/support/obfuscation'
39
- desc 'Obfuscates account.yml file.'
40
- task :obfuscate do
41
- Spec::Obfuscation.encrypt_file(File.join(File.dirname(__FILE__), 'spec', 'account.yml'))
42
- end
43
-
44
- task :deobfuscate do
45
- puts Spec::Obfuscation.decrypt_file(File.join(File.dirname(__FILE__), 'spec', 'account.yml.obfus'))
46
- end
1
+ #!/usr/bin/env rake
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ begin
10
+ require 'rdoc/task'
11
+ rescue LoadError
12
+ require 'rdoc/rdoc'
13
+ require 'rake/rdoctask'
14
+ RDoc::Task = Rake::RDocTask
15
+ end
16
+
17
+ RDoc::Task.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = "Gmail for Ruby #{Gmail::VERSION}"
20
+ rdoc.rdoc_files.include('README*')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+ Bundler::GemHelper.install_tasks
25
+
26
+ begin
27
+ require 'rspec/core/rake_task'
28
+ RSpec::Core::RakeTask.new(:spec)
29
+ rescue LoadError
30
+ task :spec do
31
+ abort 'Run `gem install rspec` to install RSpec'
32
+ end
33
+ end
34
+
35
+ task :default => :spec
36
+
37
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
38
+ require 'spec/support/obfuscation'
39
+ desc 'Obfuscates account.yml file.'
40
+ task :obfuscate do
41
+ Spec::Obfuscation.encrypt_file(File.join(File.dirname(__FILE__), 'spec', 'account.yml'))
42
+ end
43
+
44
+ task :deobfuscate do
45
+ puts Spec::Obfuscation.decrypt_file(File.join(File.dirname(__FILE__), 'spec', 'account.yml.obfus'))
46
+ end
@@ -1,34 +1,34 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- $:.push File.expand_path('../lib', __FILE__)
4
- require 'gmail/version'
5
-
6
- Gem::Specification.new do |s|
7
- s.name = "gmail"
8
- s.summary = "A Rubyesque interface to Gmail, with all the tools you will need."
9
- s.description = "A Rubyesque interface to Gmail, with all the tools you will need.
10
- Search, read and send multipart emails; archive, mark as read/unread,
11
- delete emails; and manage labels.
12
- "
13
- s.version = Gmail::VERSION
14
- s.platform = Gem::Platform::RUBY
15
- s.authors = ["Chris Kowalik"]
16
- s.email = ["chris@nu7hat.ch"]
17
- s.homepage = "http://github.com/gmailgem/gmail"
18
- s.licenses = ["MIT"]
19
-
20
- # runtime dependencies
21
- s.add_dependency "mail", ">= 2.2.1"
22
- s.add_dependency "gmail_xoauth", ">= 0.3.0"
23
-
24
- # development dependencies
25
- s.add_development_dependency "rake"
26
- s.add_development_dependency "rspec", ">= 3.1"
27
- s.add_development_dependency "rubocop"
28
- s.add_development_dependency "gem-release"
29
-
30
- s.files = `git ls-files`.split("\n")
31
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
32
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
33
- s.require_paths = ["lib"]
34
- end
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $:.push File.expand_path('../lib', __FILE__)
4
+ require 'gmail/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "gmail"
8
+ s.summary = "A Rubyesque interface to Gmail, with all the tools you will need."
9
+ s.description = "A Rubyesque interface to Gmail, with all the tools you will need.
10
+ Search, read and send multipart emails; archive, mark as read/unread,
11
+ delete emails; and manage labels.
12
+ "
13
+ s.version = Gmail::VERSION
14
+ s.platform = Gem::Platform::RUBY
15
+ s.authors = ["Chris Kowalik"]
16
+ s.email = ["chris@nu7hat.ch"]
17
+ s.homepage = "http://github.com/gmailgem/gmail"
18
+ s.licenses = ["MIT"]
19
+
20
+ # runtime dependencies
21
+ s.add_dependency "mail", ">= 2.2.1"
22
+ s.add_dependency "gmail_xoauth", ">= 0.3.0"
23
+
24
+ # development dependencies
25
+ s.add_development_dependency "rake"
26
+ s.add_development_dependency "rspec", ">= 3.1"
27
+ s.add_development_dependency "rubocop"
28
+ s.add_development_dependency "gem-release"
29
+
30
+ s.files = `git ls-files`.split("\n")
31
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
32
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
33
+ s.require_paths = ["lib"]
34
+ end
@@ -1,78 +1,78 @@
1
- require 'net/imap'
2
- require 'net/smtp'
3
- require 'mail'
4
- require 'date'
5
- require 'time'
6
-
7
- if RUBY_VERSION < "1.8.7"
8
- require "smtp_tls"
9
- end
10
-
11
- class Object
12
- def to_imap_date
13
- date = respond_to?(:utc) ? utc.to_s : to_s
14
- Date.parse(date).strftime("%d-%B-%Y")
15
- end
16
- end
17
-
18
- module Gmail
19
- autoload :Version, "gmail/version"
20
- autoload :Client, "gmail/client"
21
- autoload :Labels, "gmail/labels"
22
- autoload :Mailbox, "gmail/mailbox"
23
- autoload :Message, "gmail/message"
24
-
25
- class << self
26
- # Creates new Gmail connection using given authorization options.
27
- #
28
- # ==== Examples
29
- #
30
- # Gmail.new(:plain, "foo@gmail.com", "password")
31
- # Gmail.new(:xoauth, "foo@gmail.com",
32
- # :consumer_key => "",
33
- # :consumer_secret => "",
34
- # :token => "",
35
- # :secret => "")
36
- #
37
- # To use plain authentication mehod you can also call:
38
- #
39
- # Gmail.new("foo@gmail.com", "password")
40
- #
41
- # You can also use block-style call:
42
- #
43
- # Gmail.new("foo@gmail.com", "password") do |client|
44
- # # ...
45
- # end
46
- #
47
-
48
- def new(*args, &block)
49
- args.unshift(:plain) unless args.first.is_a?(Symbol)
50
- client = Gmail::Client.new(*args)
51
- client.connect
52
- client.login
53
-
54
- if block_given?
55
- yield client
56
- client.logout
57
- end
58
-
59
- client
60
- end
61
- alias_method :connect, :new
62
-
63
- def new!(*args, &block)
64
- args.unshift(:plain) unless args.first.is_a?(Symbol)
65
- client = Gmail::Client.new(*args)
66
- client.connect!
67
- client.login!
68
-
69
- if block_given?
70
- yield client
71
- client.logout
72
- end
73
-
74
- client
75
- end
76
- alias_method :connect!, :new!
77
- end # << self
78
- end # Gmail
1
+ require 'net/imap'
2
+ require 'net/smtp'
3
+ require 'mail'
4
+ require 'date'
5
+ require 'time'
6
+
7
+ if RUBY_VERSION < "1.8.7"
8
+ require "smtp_tls"
9
+ end
10
+
11
+ class Object
12
+ def to_imap_date
13
+ date = respond_to?(:utc) ? utc.to_s : to_s
14
+ Date.parse(date).strftime("%d-%B-%Y")
15
+ end
16
+ end
17
+
18
+ module Gmail
19
+ autoload :Version, "gmail/version"
20
+ autoload :Client, "gmail/client"
21
+ autoload :Labels, "gmail/labels"
22
+ autoload :Mailbox, "gmail/mailbox"
23
+ autoload :Message, "gmail/message"
24
+
25
+ class << self
26
+ # Creates new Gmail connection using given authorization options.
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # Gmail.new(:plain, "foo@gmail.com", "password")
31
+ # Gmail.new(:xoauth, "foo@gmail.com",
32
+ # :consumer_key => "",
33
+ # :consumer_secret => "",
34
+ # :token => "",
35
+ # :secret => "")
36
+ #
37
+ # To use plain authentication mehod you can also call:
38
+ #
39
+ # Gmail.new("foo@gmail.com", "password")
40
+ #
41
+ # You can also use block-style call:
42
+ #
43
+ # Gmail.new("foo@gmail.com", "password") do |client|
44
+ # # ...
45
+ # end
46
+ #
47
+
48
+ def new(*args, &block)
49
+ args.unshift(:plain) unless args.first.is_a?(Symbol)
50
+ client = Gmail::Client.new(*args)
51
+ client.connect
52
+ client.login
53
+
54
+ if block_given?
55
+ yield client
56
+ client.logout
57
+ end
58
+
59
+ client
60
+ end
61
+ alias_method :connect, :new
62
+
63
+ def new!(*args, &block)
64
+ args.unshift(:plain) unless args.first.is_a?(Symbol)
65
+ client = Gmail::Client.new(*args)
66
+ client.connect!
67
+ client.login!
68
+
69
+ if block_given?
70
+ yield client
71
+ client.logout
72
+ end
73
+
74
+ client
75
+ end
76
+ alias_method :connect!, :new!
77
+ end # << self
78
+ end # Gmail
@@ -1,34 +1,34 @@
1
- module Gmail
2
- module Client
3
- # Raised when connection with Gmail IMAP service couldn't be established.
4
- class ConnectionError < SocketError; end
5
- # Raised when given username or password are invalid.
6
- class AuthorizationError < Net::IMAP::NoResponseError; end
7
- # Raised when delivered email is invalid.
8
- class DeliveryError < ArgumentError; end
9
- # Raised when given client is not registered
10
- class UnknownClient < ArgumentError; end
11
-
12
- def self.clients
13
- @clients ||= {}
14
- end
15
-
16
- def self.register(name, klass)
17
- clients[name] = klass
18
- end
19
-
20
- def self.new(name, *args)
21
- if client = clients[name]
22
- client.new(*args)
23
- else
24
- raise UnknownClient, "No such client: #{name}"
25
- end
26
- end
27
-
28
- require 'gmail/imap_extensions'
29
- require 'gmail/client/base'
30
- require 'gmail/client/plain'
31
- require 'gmail/client/xoauth'
32
- require 'gmail/client/xoauth2'
33
- end # Client
34
- end # Gmail
1
+ module Gmail
2
+ module Client
3
+ # Raised when connection with Gmail IMAP service couldn't be established.
4
+ class ConnectionError < SocketError; end
5
+ # Raised when given username or password are invalid.
6
+ class AuthorizationError < Net::IMAP::NoResponseError; end
7
+ # Raised when delivered email is invalid.
8
+ class DeliveryError < ArgumentError; end
9
+ # Raised when given client is not registered
10
+ class UnknownClient < ArgumentError; end
11
+
12
+ def self.clients
13
+ @clients ||= {}
14
+ end
15
+
16
+ def self.register(name, klass)
17
+ clients[name] = klass
18
+ end
19
+
20
+ def self.new(name, *args)
21
+ if client = clients[name]
22
+ client.new(*args)
23
+ else
24
+ raise UnknownClient, "No such client: #{name}"
25
+ end
26
+ end
27
+
28
+ require 'gmail/imap_extensions'
29
+ require 'gmail/client/base'
30
+ require 'gmail/client/plain'
31
+ require 'gmail/client/xoauth'
32
+ require 'gmail/client/xoauth2'
33
+ end # Client
34
+ end # Gmail
@@ -1,229 +1,229 @@
1
- require 'thread'
2
-
3
- module Gmail
4
- module Client
5
- class Base
6
- # Gmail IMAP defaults
7
- GMAIL_IMAP_HOST = 'imap.gmail.com'
8
- GMAIL_IMAP_PORT = 993
9
-
10
- # Gmail SMTP defaults
11
- GMAIL_SMTP_HOST = "smtp.gmail.com"
12
- GMAIL_SMTP_PORT = 587
13
-
14
- attr_reader :username
15
- attr_reader :options
16
-
17
- def initialize(username, options = {})
18
- defaults = {}
19
- @username = fill_username(username)
20
- @options = defaults.merge(options)
21
- @mailbox_mutex = Mutex.new
22
- end
23
-
24
- # Connect to gmail service.
25
- def connect(raise_errors = false)
26
- @imap = Net::IMAP.new(GMAIL_IMAP_HOST, GMAIL_IMAP_PORT, true, nil, false)
27
- Gmail::ImapExtensions.patch_net_imap_response_parser
28
- @imap
29
- rescue SocketError
30
- raise_errors and raise ConnectionError, "Couldn't establish connection with Gmail IMAP service"
31
- end
32
-
33
- # This version of connect will raise error on failure...
34
- def connect!
35
- connect(true)
36
- end
37
-
38
- # Return current connection. Log in automaticaly to specified account if
39
- # it is necessary.
40
- def connection
41
- login and at_exit { logout } unless logged_in?
42
- @imap
43
- end
44
- alias :conn :connection
45
-
46
- # Login to specified account.
47
- def login(*args)
48
- raise NotImplementedError, "The `#{self.class.name}#login` method is not implemented."
49
- end
50
- alias :sign_in :login
51
-
52
- # This version of login will raise error on failure...
53
- def login!
54
- login(true)
55
- end
56
- alias :sign_in! :login!
57
-
58
- # Returns +true+ when you are logged in to specified account.
59
- def logged_in?
60
- !!@logged_in
61
- end
62
- alias :signed_in? :logged_in?
63
-
64
- # Logout from Gmail service.
65
- def logout
66
- @imap && logged_in? and @imap.logout
67
- ensure
68
- @logged_in = false
69
- end
70
- alias :sign_out :logout
71
-
72
- # Disconnect from Gmail service.
73
- def disconnect
74
- @imap && @imap.disconnect
75
- end
76
-
77
- # Return labels object, which helps you with managing your Gmail labels.
78
- # See <tt>Gmail::Labels</tt> for details.
79
- def labels
80
- @labels ||= Labels.new(conn)
81
- end
82
-
83
- # Compose new e-mail.
84
- #
85
- # ==== Examples
86
- #
87
- # mail = gmail.compose
88
- # mail.from "test@gmail.org"
89
- # mail.to "friend@gmail.com"
90
- #
91
- # ... or block style:
92
- #
93
- # mail = gmail.compose do
94
- # from "test@gmail.org"
95
- # to "friend@gmail.com"
96
- # subject "Hello!"
97
- # body "Hello my friend! long time..."
98
- # end
99
- #
100
- # Now you can deliver your mail:
101
- #
102
- # gmail.deliver(mail)
103
- def compose(mail = nil, &block)
104
- if block_given?
105
- mail = Mail.new(&block)
106
- elsif !mail
107
- mail = Mail.new
108
- end
109
-
110
- mail.delivery_method(*smtp_settings)
111
- mail.from = username unless mail.from
112
- mail
113
- end
114
- alias :message :compose
115
-
116
- # Compose (optionaly) and send given email.
117
- #
118
- # ==== Examples
119
- #
120
- # gmail.deliver do
121
- # to "friend@gmail.com"
122
- # subject "Hello friend!"
123
- # body "Hi! How are you?"
124
- # end
125
- #
126
- # ... or with already created message:
127
- #
128
- # mail = Mail.new { ... }
129
- # gmail.deliver(mail)
130
- #
131
- # mail = gmail.compose { ... }
132
- # gmail.deliver(mail)
133
- def deliver(mail = nil, raise_errors = false, &block)
134
- mail = compose(mail, &block) if block_given?
135
- mail.deliver!
136
- rescue Object => ex
137
- raise_errors and raise DeliveryError, "Couldn't deliver email: #{ex.to_s}"
138
- end
139
-
140
- # This version of deliver will raise error on failure...
141
- def deliver!(mail = nil, &block)
142
- deliver(mail, true, &block)
143
- end
144
-
145
- # Do something with given mailbox or within it context.
146
- #
147
- # ==== Examples
148
- #
149
- # mailbox = gmail.mailbox("INBOX")
150
- # mailbox.emails(:all)
151
- # mailbox.count(:unread, :before => Time.now-(20*24*3600))
152
- #
153
- # ... or block style:
154
- #
155
- # gmail.label("Work") do |mailbox|
156
- # mailbox.emails(:unread)
157
- # mailbox.count(:all)
158
- # ...
159
- # end
160
- def mailbox(name, &block)
161
- @mailbox_mutex.synchronize do
162
- name = labels.localize(name)
163
- mailbox = (mailboxes[name] ||= Mailbox.new(self, name))
164
- switch_to_mailbox(mailbox) if @current_mailbox != mailbox
165
-
166
- if block_given?
167
- mailbox_stack << @current_mailbox
168
- result = block.arity == 1 ? block.call(mailbox) : block.call
169
- mailbox_stack.pop
170
- switch_to_mailbox(mailbox_stack.last)
171
- return result
172
- end
173
-
174
- return mailbox
175
- end
176
- end
177
- alias :in_mailbox :mailbox
178
- alias :in_label :mailbox
179
- alias :label :mailbox
180
-
181
- # Alias for <tt>mailbox("INBOX")</tt>. See <tt>Gmail::Client#mailbox</tt>
182
- # for details.
183
- def inbox
184
- mailbox("INBOX")
185
- end
186
-
187
- def mailboxes
188
- @mailboxes ||= {}
189
- end
190
-
191
- def inspect
192
- "#<Gmail::Client#{'0x%04x' % (object_id << 1)} (#{username}) #{'dis' if !logged_in?}connected>"
193
- end
194
-
195
- def fill_username(username)
196
- username =~ /@/ ? username : "#{username}@gmail.com"
197
- end
198
-
199
- def mail_domain
200
- username.split('@').last
201
- end
202
-
203
- private
204
-
205
- def switch_to_mailbox(mailbox)
206
- if mailbox
207
- conn.select(mailbox.encoded_name)
208
- end
209
- @current_mailbox = mailbox
210
- end
211
-
212
- def mailbox_stack
213
- @mailbox_stack ||= []
214
- end
215
-
216
- def smtp_settings
217
- [:smtp, {
218
- :address => GMAIL_SMTP_HOST,
219
- :port => GMAIL_SMTP_PORT,
220
- :domain => mail_domain,
221
- :user_name => username,
222
- :password => password,
223
- :authentication => 'plain',
224
- :enable_starttls_auto => true
225
- }]
226
- end
227
- end # Base
228
- end # Client
229
- end # Gmail
1
+ require 'thread'
2
+
3
+ module Gmail
4
+ module Client
5
+ class Base
6
+ # Gmail IMAP defaults
7
+ GMAIL_IMAP_HOST = 'imap.gmail.com'
8
+ GMAIL_IMAP_PORT = 993
9
+
10
+ # Gmail SMTP defaults
11
+ GMAIL_SMTP_HOST = "smtp.gmail.com"
12
+ GMAIL_SMTP_PORT = 587
13
+
14
+ attr_reader :username
15
+ attr_reader :options
16
+
17
+ def initialize(username, options = {})
18
+ defaults = {}
19
+ @username = fill_username(username)
20
+ @options = defaults.merge(options)
21
+ @mailbox_mutex = Mutex.new
22
+ end
23
+
24
+ # Connect to gmail service.
25
+ def connect(raise_errors = false)
26
+ @imap = Net::IMAP.new(GMAIL_IMAP_HOST, GMAIL_IMAP_PORT, true, nil, false)
27
+ Gmail::ImapExtensions.patch_net_imap_response_parser
28
+ @imap
29
+ rescue SocketError
30
+ raise_errors and raise ConnectionError, "Couldn't establish connection with Gmail IMAP service"
31
+ end
32
+
33
+ # This version of connect will raise error on failure...
34
+ def connect!
35
+ connect(true)
36
+ end
37
+
38
+ # Return current connection. Log in automaticaly to specified account if
39
+ # it is necessary.
40
+ def connection
41
+ login and at_exit { logout } unless logged_in?
42
+ @imap
43
+ end
44
+ alias :conn :connection
45
+
46
+ # Login to specified account.
47
+ def login(*args)
48
+ raise NotImplementedError, "The `#{self.class.name}#login` method is not implemented."
49
+ end
50
+ alias :sign_in :login
51
+
52
+ # This version of login will raise error on failure...
53
+ def login!
54
+ login(true)
55
+ end
56
+ alias :sign_in! :login!
57
+
58
+ # Returns +true+ when you are logged in to specified account.
59
+ def logged_in?
60
+ !!@logged_in
61
+ end
62
+ alias :signed_in? :logged_in?
63
+
64
+ # Logout from Gmail service.
65
+ def logout
66
+ @imap && logged_in? and @imap.logout
67
+ ensure
68
+ @logged_in = false
69
+ end
70
+ alias :sign_out :logout
71
+
72
+ # Disconnect from Gmail service.
73
+ def disconnect
74
+ @imap && @imap.disconnect
75
+ end
76
+
77
+ # Return labels object, which helps you with managing your Gmail labels.
78
+ # See <tt>Gmail::Labels</tt> for details.
79
+ def labels
80
+ @labels ||= Labels.new(conn)
81
+ end
82
+
83
+ # Compose new e-mail.
84
+ #
85
+ # ==== Examples
86
+ #
87
+ # mail = gmail.compose
88
+ # mail.from "test@gmail.org"
89
+ # mail.to "friend@gmail.com"
90
+ #
91
+ # ... or block style:
92
+ #
93
+ # mail = gmail.compose do
94
+ # from "test@gmail.org"
95
+ # to "friend@gmail.com"
96
+ # subject "Hello!"
97
+ # body "Hello my friend! long time..."
98
+ # end
99
+ #
100
+ # Now you can deliver your mail:
101
+ #
102
+ # gmail.deliver(mail)
103
+ def compose(mail = nil, &block)
104
+ if block_given?
105
+ mail = Mail.new(&block)
106
+ elsif !mail
107
+ mail = Mail.new
108
+ end
109
+
110
+ mail.delivery_method(*smtp_settings)
111
+ mail.from = username unless mail.from
112
+ mail
113
+ end
114
+ alias :message :compose
115
+
116
+ # Compose (optionaly) and send given email.
117
+ #
118
+ # ==== Examples
119
+ #
120
+ # gmail.deliver do
121
+ # to "friend@gmail.com"
122
+ # subject "Hello friend!"
123
+ # body "Hi! How are you?"
124
+ # end
125
+ #
126
+ # ... or with already created message:
127
+ #
128
+ # mail = Mail.new { ... }
129
+ # gmail.deliver(mail)
130
+ #
131
+ # mail = gmail.compose { ... }
132
+ # gmail.deliver(mail)
133
+ def deliver(mail = nil, raise_errors = false, &block)
134
+ mail = compose(mail, &block)
135
+ mail.deliver!
136
+ rescue Object => ex
137
+ raise_errors and raise DeliveryError, "Couldn't deliver email: #{ex.to_s}"
138
+ end
139
+
140
+ # This version of deliver will raise error on failure...
141
+ def deliver!(mail = nil, &block)
142
+ deliver(mail, true, &block)
143
+ end
144
+
145
+ # Do something with given mailbox or within it context.
146
+ #
147
+ # ==== Examples
148
+ #
149
+ # mailbox = gmail.mailbox("INBOX")
150
+ # mailbox.emails(:all)
151
+ # mailbox.count(:unread, :before => Time.now-(20*24*3600))
152
+ #
153
+ # ... or block style:
154
+ #
155
+ # gmail.label("Work") do |mailbox|
156
+ # mailbox.emails(:unread)
157
+ # mailbox.count(:all)
158
+ # ...
159
+ # end
160
+ def mailbox(name, &block)
161
+ @mailbox_mutex.synchronize do
162
+ name = labels.localize(name)
163
+ mailbox = (mailboxes[name] ||= Mailbox.new(self, name))
164
+ switch_to_mailbox(mailbox) if @current_mailbox != mailbox
165
+
166
+ if block_given?
167
+ mailbox_stack << @current_mailbox
168
+ result = block.arity == 1 ? block.call(mailbox) : block.call
169
+ mailbox_stack.pop
170
+ switch_to_mailbox(mailbox_stack.last)
171
+ return result
172
+ end
173
+
174
+ return mailbox
175
+ end
176
+ end
177
+ alias :in_mailbox :mailbox
178
+ alias :in_label :mailbox
179
+ alias :label :mailbox
180
+
181
+ # Alias for <tt>mailbox("INBOX")</tt>. See <tt>Gmail::Client#mailbox</tt>
182
+ # for details.
183
+ def inbox
184
+ mailbox("INBOX")
185
+ end
186
+
187
+ def mailboxes
188
+ @mailboxes ||= {}
189
+ end
190
+
191
+ def inspect
192
+ "#<Gmail::Client#{'0x%04x' % (object_id << 1)} (#{username}) #{'dis' if !logged_in?}connected>"
193
+ end
194
+
195
+ def fill_username(username)
196
+ username =~ /@/ ? username : "#{username}@gmail.com"
197
+ end
198
+
199
+ def mail_domain
200
+ username.split('@').last
201
+ end
202
+
203
+ private
204
+
205
+ def switch_to_mailbox(mailbox)
206
+ if mailbox
207
+ conn.select(mailbox.encoded_name)
208
+ end
209
+ @current_mailbox = mailbox
210
+ end
211
+
212
+ def mailbox_stack
213
+ @mailbox_stack ||= []
214
+ end
215
+
216
+ def smtp_settings
217
+ [:smtp, {
218
+ :address => GMAIL_SMTP_HOST,
219
+ :port => GMAIL_SMTP_PORT,
220
+ :domain => mail_domain,
221
+ :user_name => username,
222
+ :password => password,
223
+ :authentication => 'plain',
224
+ :enable_starttls_auto => true
225
+ }]
226
+ end
227
+ end # Base
228
+ end # Client
229
+ end # Gmail