wco_models 3.1.0.53 → 3.1.0.55

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e600845398a0cd10bcd4683dfd01a7f3793ba4b1dc9e086df508d1845fc8127
4
- data.tar.gz: a8f500decf7e7f67716cdcf3e53231239bedb36e3ee8098a0a27063ef80068f9
3
+ metadata.gz: 5ae4d6cc7110308649e7a5712cbfe581d43d60020e4033bf2df363578ee65db2
4
+ data.tar.gz: 842a7799e8f0d6808b1899913ce4aeb6f6088e10df079c6ecdf845329ed566c0
5
5
  SHA512:
6
- metadata.gz: a5649ea010caf2ecba1b71bfdd800f4674320a5c36ac95c7aab2f0b9266d19eedfbb37ed3a91785c9e4bc8a80c4aeccc848e3709018d81c3bc427ddee740dbde
7
- data.tar.gz: 8a7e153a876fe7f28c411c056e838f08e204f1d4647add4a72c68718474b8dc971af71105d7cd455bb4934b43a62560f752e29da1ac4d8f1f12475718f074cf0
6
+ metadata.gz: 99f8d28d0370c8c0d080c3c622ef6f1f989c8384be29ba28ba062edd60a05f12183a7a37e73c4b19f9e05f10cd4c4d575e7d81ca5112a2c7d6497d793268f845
7
+ data.tar.gz: e85181146abbaf57ef9cbca611620fade206ea94ee0f0af5853ed912fa0647c181729e309f24080e3c278e6e9ceb2ddc67d8396eeaa4d9f6ece5437d6f9a0492
@@ -113,6 +113,10 @@ h5.title {
113
113
  display: flex;
114
114
  }
115
115
 
116
+ .h-500px {
117
+ min-height: 500px;
118
+ }
119
+
116
120
  /* M */
117
121
 
118
122
  .maxwidth {
@@ -14,6 +14,12 @@ class Wco::Lead
14
14
  field :address
15
15
 
16
16
  belongs_to :leadset, class_name: 'Wco::Leadset'
17
+ before_validation :set_leadset, on: :create
18
+ def set_leadset
19
+ domain = email.split('@')[1]
20
+ self.leadset ||= Wco::Leadset.find_or_create_by({ company_url: domain })
21
+ end
22
+
17
23
  has_one :photo, class_name: 'Wco::Photo'
18
24
 
19
25
  has_many :email_messages, class_name: '::WcoEmail::Message', inverse_of: :lead
@@ -25,7 +25,7 @@ class WcoEmail::Context
25
25
  if self[:body].presence
26
26
  return self[:body]
27
27
  else
28
- return tmpl.body
28
+ return tmpl&.body || ''
29
29
  end
30
30
  end
31
31
 
@@ -35,8 +35,10 @@ class WcoEmail::Context
35
35
  def from_email
36
36
  if self[:from_email].presence
37
37
  return self[:from_email]
38
- else
38
+ elsif tmpl&.from_email
39
39
  return tmpl.from_email
40
+ else
41
+ return DEFAULT_FROM_EMAIL
40
42
  end
41
43
  end
42
44
 
@@ -1,4 +1,6 @@
1
1
 
2
+ DEFAULT_FROM_EMAIL = 'victor@wasya.co'
3
+
2
4
  class WcoEmail::EmailTemplate
3
5
  include Mongoid::Document
4
6
  include Mongoid::Timestamps
@@ -86,9 +88,20 @@ class WcoEmail::EmailTemplate
86
88
  'Wasya Co Mailer <no-reply@wco.com.de>',
87
89
  'Wasya Co Mailer <wasyacomailer@gmail.com>',
88
90
  ];
91
+ FROM_EMAILS_2 = [
92
+
93
+ [ 'Victor Pudeyev <piousbox@gmail.com>', 'piousbox@gmail.com' ],
94
+ [ 'Victor Pudeyev <victor@piousbox.com>', 'victor@piousbox.com' ],
95
+ [ 'Victor Pudeyev <no-reply@piousbox.com>', 'no-reply@piousbox.com' ],
96
+
97
+ [ 'WasyaCo Consulting <no-reply@wasya.co>', 'no-reply@wasya.co' ],
98
+ [ 'Victor Pudeyev <victor@wasya.co>', 'victor@wasya.co' ],
99
+
100
+ ];
89
101
  field :from_email
90
- def self.from_email_list
91
- [ [nil, nil] ] + FROM_EMAILS.map { |i| [i, i] }
102
+ def self.from_emails_list
103
+ # [ [nil, nil] ] + FROM_EMAILS.map { |i| [i, i] }
104
+ FROM_EMAILS_2
92
105
  end
93
106
 
94
107
  SIGNATURE = <<~AOL
@@ -118,7 +131,7 @@ class WcoEmail::EmailTemplate
118
131
  def self.blank; self.blank_template; end
119
132
 
120
133
  def self.list
121
- all.map { |p| [ p.id, p.slug ] }
134
+ all.map { |p| [ p.slug, p.id ] }
122
135
  end
123
136
 
124
137
  end
@@ -67,7 +67,7 @@ class WcoEmail::Message
67
67
  def received_at ; date ; end
68
68
 
69
69
  belongs_to :conversation, class_name: 'WcoEmail::Conversation'
70
- def conv ; email_conversation ; end
70
+ def conv ; conversation ; end
71
71
 
72
72
  belongs_to :stub, class_name: 'WcoEmail::MessageStub'
73
73
 
@@ -1,4 +1,10 @@
1
1
 
2
+ =begin
3
+
4
+ key = '01070861907736276273039d9ee-c69a3509-5c85-481d-822e-ba65c204e1ba-000000@eu-central-1.amazonses.com'
5
+
6
+ =end
7
+
2
8
  ##
3
9
  ## Only object_key, no validations.
4
10
  ## 2023-12-28 _vp_ Continue.
@@ -13,9 +19,9 @@ class WcoEmail::MessageStub
13
19
  STATUS_PENDING = 'status_pending'
14
20
  STATUS_PROCESSED = 'status_processed'
15
21
  STATUS_FAILED = 'status_failed'
16
- STATUSES = [ STATUS_PENDING, STATUS_PROCESSED ]
22
+ STATUSES = [ STATUS_PENDING, STATUS_PROCESSED, STATUS_FAILED ]
17
23
  field :status, default: STATUS_PENDING
18
- scope :pending, ->{ where( status: 'status_pending' ) }
24
+ scope :pending, ->{ where( status: STATUS_PENDING ) }
19
25
 
20
26
  field :bucket # 'ish-ses', 'ish-ses-2024'
21
27
 
@@ -31,8 +37,180 @@ class WcoEmail::MessageStub
31
37
  {}
32
38
  AOL
33
39
 
34
- ## This only saves a local messafe from mbox to s3.
35
- def do_process message
40
+ def do_process
41
+ @client ||= Aws::S3::Client.new({
42
+ region: ::S3_CREDENTIALS[:region_ses],
43
+ access_key_id: ::S3_CREDENTIALS[:access_key_id_ses],
44
+ secret_access_key: ::S3_CREDENTIALS[:secret_access_key_ses],
45
+ })
46
+ stub = self
47
+
48
+ raw = @client.get_object( bucket: stub.bucket, key: stub.object_key ).body.read
49
+ the_mail = Mail.new( raw )
50
+
51
+ message_id = the_mail.header['message-id']&.decoded
52
+ message_id ||= "#{the_mail.date&.iso8601}::#{the_mail.from}"
53
+ # puts! message_id, 'message_id'
54
+
55
+ in_reply_to_id = the_mail.header['in-reply-to']&.to_s
56
+ puts! in_reply_to_id, 'in_reply_to_id'
57
+
58
+ the_mail.to = [ 'NO-RECIPIENT' ] if !the_mail.to
59
+ subject = WcoEmail::Message.strip_emoji( the_mail.subject || '(wco-no-subject)' )
60
+ puts! subject, 'subject'
61
+
62
+ ## Conversation
63
+ if in_reply_to_id
64
+ in_reply_to_msg = WcoEmail::Message.where({ message_id: in_reply_to_id }).first
65
+ if !in_reply_to_msg
66
+ conv = WcoEmail::Conversation.find_or_create_by({
67
+ subject: subject,
68
+ })
69
+ in_reply_to_msg = WcoEmail::Message.find_or_create_by({
70
+ message_id: in_reply_to_id,
71
+ conversation: conv,
72
+ })
73
+ end
74
+ conv = in_reply_to_msg.conversation
75
+ else
76
+ conv = WcoEmail::Conversation.find_or_create_by({
77
+ subject: subject,
78
+ })
79
+ end
80
+
81
+
82
+ ## Leadset, Lead
83
+ from = the_mail.from ? the_mail.from[0] : "nobody@unknown-doma.in"
84
+ domain = from.split('@')[1]
85
+ leadset = Wco::Leadset.where( company_url: domain ).first
86
+ leadset ||= Wco::Leadset.create( company_url: domain, email: from )
87
+ lead = Wco::Lead.find_or_create_by( email: from, leadset: leadset )
88
+
89
+
90
+ message = WcoEmail::Message.unscoped.where( message_id: message_id ).first
91
+ if message
92
+ message.message_id = "#{Time.now.strftime('%Y%m%d')}-trash-#{message.message_id}"
93
+ message.object_key = "#{Time.now.strftime('%Y%m%d')}-trash-#{message.object_key}"
94
+ message.save!( validate: false )
95
+ message.delete
96
+ end
97
+ @message = WcoEmail::Message.create!({
98
+ stub: stub,
99
+ conversation: conv,
100
+ lead: lead,
101
+
102
+ message_id: message_id,
103
+ in_reply_to_id: in_reply_to_id,
104
+ object_key: stub.object_key,
105
+
106
+ subject: subject,
107
+ date: the_mail.date,
108
+
109
+ from: from,
110
+ froms: the_mail.from,
111
+
112
+ to: the_mail.to ? the_mail.to[0] : nil,
113
+ tos: the_mail.to,
114
+
115
+ cc: the_mail.cc ? the_mail.cc[0] : nil,
116
+ ccs: the_mail.cc,
117
+ })
118
+
119
+ ## Parts
120
+ the_mail.parts.each do |part|
121
+ @message.churn_subpart( part )
122
+ end
123
+ @message.save
124
+
125
+ if the_mail.parts.length == 0
126
+ body = the_mail.body.decoded.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
127
+ if the_mail.content_type&.include?('text/html')
128
+ @message.part_html = body
129
+ elsif the_mail.content_type&.include?('text/plain')
130
+ @message.part_txt = body
131
+ elsif the_mail.content_type.blank?
132
+ @message.part_txt = body
133
+ else
134
+ @message.logs.push "mail body of unknown type: #{the_mail.content_type}"
135
+ end
136
+ @message.save
137
+ end
138
+
139
+ ## Attachments
140
+ the_mail.attachments.each do |att|
141
+ @message.save_attachment( att )
142
+ end
143
+
144
+ if !@message.save
145
+ puts! @message.errors.full_messages.join(", "), "Could not save @message"
146
+ end
147
+
148
+
149
+ conv.leads.push lead
150
+ conv.save
151
+ # lead.conversations.push conv
152
+ # lead.save
153
+
154
+ the_mail.cc&.each do |cc|
155
+ domain = cc.split('@')[1] rescue 'unknown.domain'
156
+ leadset = Wco::Leadset.find_or_create_by( company_url: domain )
157
+ Wco::Lead.find_or_create_by( email: cc, leadset: leadset )
158
+ end
159
+
160
+ conv.update_attributes({
161
+ status: WcoEmail::Conversation::STATUS_UNREAD,
162
+ latest_at: the_mail.date || Time.now.to_datetime,
163
+ from_emails: ( conv.from_emails + the_mail.from ).uniq,
164
+ preview: @message.preview_str,
165
+ })
166
+
167
+ ##
168
+ ## Tags
169
+ ##
170
+ inbox_tag = Wco::Tag.inbox
171
+ conv.tags.push inbox_tag
172
+ conv.tags.push stub.tags
173
+ conv.save
174
+ # inbox_tag.conversations.push conv
175
+ # inbox_tag.save
176
+
177
+
178
+ ## Actions & Filters
179
+ email_filters = WcoEmail::EmailFilter.active
180
+ email_filters.each do |filter|
181
+ if ( filter.from_regex.blank? || @message.from.match( filter.from_regex ) ) &&
182
+ ( filter.from_exact.blank? || @message.from.downcase.include?( filter.from_exact&.downcase ) ) &&
183
+ ( filter.body_exact.blank? || @message.part_html&.include?( filter.body_exact ) ) &&
184
+ ( filter.subject_regex.blank? || @message.subject.match( filter.subject_regex ) ) &&
185
+ ( filter.subject_exact.blank? || @message.subject.downcase.include?( filter.subject_exact&.downcase ) )
186
+
187
+ # || MiaTagger.analyze( @message.part_html, :is_spammy_recruite ).score > .5
188
+
189
+ puts! "applying filter #{filter} to conv #{conv}" if DEBUG
190
+
191
+ @message.apply_filter( filter )
192
+ end
193
+ end
194
+
195
+ stub.update_attributes({ status: WcoEmail::MessageStub::STATUS_PROCESSED })
196
+
197
+ ## Notification
198
+ config = JSON.parse(stub.config)
199
+ if config['skip_notification']
200
+ ;
201
+ else
202
+ conv = WcoEmail::Conversation.find( conv.id )
203
+ if conv.tags.include? inbox_tag
204
+ out = WcoEmail::ApplicationMailer.forwarder_notify( @message.id.to_s )
205
+ Rails.env.production? ? out.deliver_later : out.deliver_now
206
+ end
207
+ end
208
+
209
+ puts 'ok'
210
+ end
211
+
212
+ ## This only saves a local message from mbox to s3.
213
+ def save_mbox_to_m3 message
36
214
  the_mail = Mail.new(message)
37
215
  key = the_mail.message_id || "no-key-#{Time.now.to_i}.#{rand(1000)}"
38
216
 
@@ -82,7 +260,7 @@ class WcoEmail::MessageStub
82
260
 
83
261
  if message
84
262
  if skip < @count
85
- do_process message
263
+ save_mbox_to_m3 message
86
264
  print "#{@count}."
87
265
  else
88
266
  print "s-#{@count}."
@@ -98,7 +276,7 @@ class WcoEmail::MessageStub
98
276
 
99
277
  if message
100
278
  if skip < @count
101
- do_process message
279
+ save_mbox_to_m3 message
102
280
  print "#{@count}."
103
281
  else
104
282
  print "s-#{@count}."
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wco_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0.53
4
+ version: 3.1.0.55
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Pudeyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-10 00:00:00.000000000 Z
11
+ date: 2024-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-s3