gmail 0.5.0 → 0.6.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.
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