sipo_mailer 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 35eb2910aa10ad4d9aa5828307ccdd78f2a12c4e
4
+ data.tar.gz: d411582229cbb92b754b7d75b435a1132b1ce66c
5
+ SHA512:
6
+ metadata.gz: 2afa7e759d778b70e88cb9e25307afe648bc858e8de2ef07fc6536694b6560145e9cde8b76440cb28cc619299867bf6fd92401c5d3c632974fda99cf080cc91a
7
+ data.tar.gz: 0dd2339f220f4baadf8cd3a77220b54ab63c21b59447e98f0375abf059c944bd2b9da9a00a6e671beb8be6bd6f0520e71822dc34441d41394a525cb6622001b7
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ local_data/**
2
+ tmp/
3
+ docs/**
4
+ config/config.yml
5
+ **/**/.DS_Store
6
+ *.gem
data/.rubocop.yml ADDED
@@ -0,0 +1,64 @@
1
+ # This is the configuration used to check the rubocop source code.
2
+
3
+ inherit_from: .rubocop_todo.yml
4
+
5
+ AllCops:
6
+ Exclude:
7
+ - 'config/initializers/active_record_monkey_patch.rb'
8
+ CacheRootDirectory: './tmp'
9
+
10
+ Style/PredicateName:
11
+ Exclude:
12
+ - 'spec/support/feature_macros.rb'
13
+
14
+ Style/WordArray:
15
+ MinSize: 3
16
+
17
+ Style/SymbolProc:
18
+ IgnoredMethods: validate
19
+
20
+ Style/Documentation:
21
+ Enabled: false
22
+
23
+ Style/SingleLineBlockParams:
24
+ Enabled: false
25
+
26
+ Lint/UselessAccessModifier:
27
+ Enabled: false
28
+
29
+ Style/GuardClause:
30
+ Enabled: false
31
+
32
+ Style/PredicateName:
33
+ Enabled: false
34
+
35
+ Metrics/ModuleLength:
36
+ Max: 205
37
+
38
+ Metrics/LineLength:
39
+ Enabled: false
40
+
41
+ Style/EmptyMethod:
42
+ Enabled: false
43
+
44
+ Style/WordArray:
45
+ Enabled: false
46
+
47
+ # default zarovnavani vim
48
+ # ignoruje hash pokud jej pouzivame napr. jako parametr:
49
+ #
50
+ # mail to: 'info@uol.cz',
51
+ # subject: "Message: #{message.name}",
52
+ Layout/AlignHash:
53
+ EnforcedLastArgumentHashStyle: 'ignore_implicit'
54
+
55
+ # TODO vim jinak zarovnava pokud je metoda volana se zavorkou nebo bez
56
+ #
57
+ # create(:job,
58
+ # title: "Ucetni"
59
+ # VS
60
+ #
61
+ # create :job,
62
+ # title: "Ucetni"
63
+ Layout/AlignParameters:
64
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,463 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-01-15 09:04:51 +0100 using RuboCop version 0.49.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 29
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: Include, TreatCommentsAsGroupSeparators.
12
+ # Include: **/Gemfile, **/gems.rb
13
+ Bundler/OrderedGems:
14
+ Exclude:
15
+ - 'Gemfile'
16
+
17
+ # Offense count: 3
18
+ # Cop supports --auto-correct.
19
+ Layout/EmptyLinesAroundExceptionHandlingKeywords:
20
+ Exclude:
21
+ - 'app/models/document_template.rb'
22
+ - 'app/models/sales_invoice_import.rb'
23
+ - 'lib/tasks/import_currencies_exchange.rake'
24
+
25
+ # Offense count: 5
26
+ # Cop supports --auto-correct.
27
+ # Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
28
+ Layout/ExtraSpacing:
29
+ Exclude:
30
+ - 'app/controllers/users_controller.rb'
31
+ - 'app/models/contact.rb'
32
+ - 'app/models/offer.rb'
33
+ - 'app/models/sales_order.rb'
34
+
35
+ # Offense count: 1
36
+ # Cop supports --auto-correct.
37
+ # Configuration parameters: IndentationWidth.
38
+ Layout/IndentAssignment:
39
+ Exclude:
40
+ - 'app/services/cash_book_data_generator.rb'
41
+
42
+ # Offense count: 6
43
+ # Cop supports --auto-correct.
44
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
45
+ # SupportedStyles: symmetrical, new_line, same_line
46
+ Layout/MultilineArrayBraceLayout:
47
+ Exclude:
48
+ - 'app/controllers/application_controller.rb'
49
+ - 'spec/fixtures/payables.rb'
50
+ - 'spec/policies/sales_order_policy_spec.rb'
51
+
52
+ # Offense count: 57
53
+ # Cop supports --auto-correct.
54
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
55
+ # SupportedStyles: symmetrical, new_line, same_line
56
+ Layout/MultilineHashBraceLayout:
57
+ Enabled: false
58
+
59
+ # Offense count: 14
60
+ # Cop supports --auto-correct.
61
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
62
+ # SupportedStyles: symmetrical, new_line, same_line
63
+ Layout/MultilineMethodCallBraceLayout:
64
+ Exclude:
65
+ - 'app/services/accounting_records_pdf_generator.rb'
66
+ - 'spec/factories/uploaded_documents.rb'
67
+ - 'spec/models/address_spec.rb'
68
+ - 'spec/models/contact_spec.rb'
69
+ - 'spec/models/invitation_spec.rb'
70
+ - 'spec/services/paypal/statement_fetcher_spec.rb'
71
+ - 'spec/support/shared_examples/base_send_by.rb'
72
+
73
+ # Offense count: 113
74
+ # Cop supports --auto-correct.
75
+ # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
76
+ # SupportedStyles: aligned, indented, indented_relative_to_receiver
77
+ Layout/MultilineMethodCallIndentation:
78
+ Enabled: false
79
+
80
+ # Offense count: 11
81
+ # Cop supports --auto-correct.
82
+ # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
83
+ # SupportedStyles: aligned, indented
84
+ Layout/MultilineOperationIndentation:
85
+ Exclude:
86
+ - 'app/mailers/invitation_mailer.rb'
87
+ - 'app/models/address.rb'
88
+ - 'app/models/sales_invoice.rb'
89
+ - 'app/models/sales_invoice_item.rb'
90
+ - 'lib/tasks/intrastat_report.rake'
91
+ - 'lib/tenant_builder.rb'
92
+
93
+ # Offense count: 1
94
+ # Cop supports --auto-correct.
95
+ Layout/SpaceAroundKeyword:
96
+ Exclude:
97
+ - 'app/models/sales_order.rb'
98
+
99
+ # Offense count: 1
100
+ # Cop supports --auto-correct.
101
+ # Configuration parameters: AllowForAlignment.
102
+ Layout/SpaceAroundOperators:
103
+ Exclude:
104
+ - 'app/controllers/products/products_controller.rb'
105
+
106
+ # Offense count: 9
107
+ # Cop supports --auto-correct.
108
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
109
+ # SupportedStyles: require_no_space, require_space
110
+ Layout/SpaceInLambdaLiteral:
111
+ Exclude:
112
+ - 'app/models/accounting_record.rb'
113
+ - 'app/models/currency_pair.rb'
114
+ - 'app/models/logo.rb'
115
+ - 'app/models/message.rb'
116
+ - 'app/models/product.rb'
117
+ - 'config/environments/production.rb'
118
+
119
+ # Offense count: 18
120
+ # Cop supports --auto-correct.
121
+ Layout/SpaceInsidePercentLiteralDelimiters:
122
+ Exclude:
123
+ - 'app/models/concerns/after_document_issue_attributes.rb'
124
+ - 'app/models/my_bank_account.rb'
125
+ - 'app/models/my_company.rb'
126
+ - 'app/models/vat_rate.rb'
127
+ - 'config/initializers/assets.rb'
128
+ - 'spec/models/my_bank_account_spec.rb'
129
+ - 'spec/models/sales_order_spec.rb'
130
+
131
+ # Offense count: 5
132
+ Lint/AmbiguousBlockAssociation:
133
+ Exclude:
134
+ - 'spec/models/tenant_spec.rb'
135
+ - 'spec/services/document_template_manager_spec.rb'
136
+ - 'spec/services/paypal/balance_fetcher_spec.rb'
137
+ - 'spec/services/paypal/statement_fetcher_spec.rb'
138
+
139
+ # Offense count: 9
140
+ Lint/IneffectiveAccessModifier:
141
+ Exclude:
142
+ - 'app/data_objects/interval.rb'
143
+ - 'app/models/setting.rb'
144
+ - 'app/models/tenant.rb'
145
+ - 'app/services/public_id_guesser.rb'
146
+ - 'lib/expert_fantozzi_contract.rb'
147
+ - 'lib/ldap_user_finder.rb'
148
+
149
+ # Offense count: 1
150
+ # Cop supports --auto-correct.
151
+ Lint/UnifiedInteger:
152
+ Exclude:
153
+ - 'spec/support/rspec_matchers/have_row.rb'
154
+
155
+ # Offense count: 1
156
+ # Cop supports --auto-correct.
157
+ Lint/UnneededDisable:
158
+ Exclude:
159
+ - 'app/queries/query/budget_by_days.rb'
160
+
161
+ # Offense count: 1
162
+ # Cop supports --auto-correct.
163
+ Lint/UnneededSplatExpansion:
164
+ Exclude:
165
+ - 'app/api/v1/sales_orders.rb'
166
+
167
+ # Offense count: 272
168
+ Metrics/AbcSize:
169
+ Max: 169
170
+
171
+ # Offense count: 607
172
+ # Configuration parameters: CountComments, ExcludedMethods.
173
+ Metrics/BlockLength:
174
+ Max: 1260
175
+
176
+ # Offense count: 42
177
+ # Configuration parameters: CountComments.
178
+ Metrics/ClassLength:
179
+ Max: 302
180
+
181
+ # Offense count: 56
182
+ Metrics/CyclomaticComplexity:
183
+ Max: 17
184
+
185
+ # Offense count: 219
186
+ # Configuration parameters: CountComments.
187
+ Metrics/MethodLength:
188
+ Max: 125
189
+
190
+ # Offense count: 6
191
+ # Configuration parameters: CountKeywordArgs.
192
+ Metrics/ParameterLists:
193
+ Max: 7
194
+
195
+ # Offense count: 37
196
+ Metrics/PerceivedComplexity:
197
+ Max: 17
198
+
199
+ # Offense count: 1
200
+ # Cop supports --auto-correct.
201
+ Performance/Casecmp:
202
+ Exclude:
203
+ - 'app/models/product.rb'
204
+
205
+ # Offense count: 5
206
+ # Cop supports --auto-correct.
207
+ Performance/RangeInclude:
208
+ Exclude:
209
+ - 'app/models/accounting_period.rb'
210
+ - 'app/validators/vatin_validator.rb'
211
+ - 'lib/tasks/intrastat_report.rake'
212
+
213
+ # Offense count: 1
214
+ # Cop supports --auto-correct.
215
+ Performance/RedundantBlockCall:
216
+ Exclude:
217
+ - 'spec/support/database_helper.rb'
218
+
219
+ # Offense count: 8
220
+ # Cop supports --auto-correct.
221
+ # Configuration parameters: MaxKeyValuePairs.
222
+ Performance/RedundantMerge:
223
+ Exclude:
224
+ - 'app/api/v1/demands_for_payment.rb'
225
+ - 'app/api/v1/my_bank_accounts.rb'
226
+ - 'app/api/v1/pagination_helpers.rb'
227
+ - 'app/services/frontend_modifier_symbolizer.rb'
228
+ - 'app/services/modifier_symbolizer.rb'
229
+ - 'spec/api/v1/contacts_spec.rb'
230
+
231
+ # Offense count: 3
232
+ # Cop supports --auto-correct.
233
+ Security/YAMLLoad:
234
+ Exclude:
235
+ - 'config/application.rb'
236
+ - 'lib/ldap_user_finder.rb'
237
+ - 'lib/tasks/migrate.rake'
238
+
239
+ # Offense count: 6
240
+ # Cop supports --auto-correct.
241
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
242
+ # SupportedStyles: prefer_alias, prefer_alias_method
243
+ Style/Alias:
244
+ Exclude:
245
+ - 'app/models/search/sales_order.rb'
246
+ - 'app/models/user_permission.rb'
247
+ - 'app/models/user_permissions_collection.rb'
248
+ - 'app/services/subject_to_vat_specification.rb'
249
+
250
+ # Offense count: 10
251
+ Style/AsciiComments:
252
+ Exclude:
253
+ - 'app/controllers/application_controller.rb'
254
+ - 'app/models/currency.rb'
255
+ - 'app/workers/cost_revenue_worker_base.rb'
256
+ - 'spec/factories/reports.rb'
257
+ - 'spec/models/my_bank_account_spec.rb'
258
+ - 'spec/models/vat_rate_spec.rb'
259
+
260
+ # Offense count: 6
261
+ # Cop supports --auto-correct.
262
+ # Configuration parameters: EnforcedStyle, SupportedStyles, SingleLineConditionsOnly, IncludeTernaryExpressions.
263
+ # SupportedStyles: assign_to_condition, assign_inside_condition
264
+ Style/ConditionalAssignment:
265
+ Exclude:
266
+ - 'app/helpers/invoice_helper.rb'
267
+ - 'app/models/address.rb'
268
+ - 'app/models/product.rb'
269
+ - 'app/services/cash_book_data_generator.rb'
270
+ - 'app/validators/bank_account_or_iban_validator.rb'
271
+ - 'app/validators/sales_invoice_validator.rb'
272
+
273
+ # Offense count: 4
274
+ # Cop supports --auto-correct.
275
+ Style/EmptyCaseCondition:
276
+ Exclude:
277
+ - 'app/decorators/concerns/document_addresses.rb'
278
+ - 'app/services/subject_to_vat_specification.rb'
279
+ - 'app/validators/linked_doc_validator.rb'
280
+
281
+ # Offense count: 1294
282
+ # Cop supports --auto-correct.
283
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
284
+ # SupportedStyles: when_needed, always, never
285
+ Style/FrozenStringLiteralComment:
286
+ Enabled: false
287
+
288
+ # Offense count: 2
289
+ Style/IdenticalConditionalBranches:
290
+ Exclude:
291
+ - 'lib/tasks/export_accounting_records_to_pdf.rake'
292
+
293
+ # Offense count: 10
294
+ Style/IfInsideElse:
295
+ Exclude:
296
+ - 'app/controllers/logos_controller.rb'
297
+ - 'app/models/currency_pair.rb'
298
+ - 'app/models/default_attrs/purchase_invoice.rb'
299
+ - 'app/models/purchase_invoice_item.rb'
300
+ - 'app/queries/query/receivables_core.rb'
301
+ - 'app/services/currency_exchange.rb'
302
+ - 'app/services/subject_to_vat_specification.rb'
303
+ - 'app/validators/vatin_validator.rb'
304
+
305
+ # Offense count: 1
306
+ # Cop supports --auto-correct.
307
+ # Configuration parameters: MaxLineLength.
308
+ Style/IfUnlessModifier:
309
+ Exclude:
310
+ - 'app/validators/vatin_validator.rb'
311
+
312
+ # Offense count: 2
313
+ # Cop supports --auto-correct.
314
+ # Configuration parameters: InverseMethods, InverseBlocks.
315
+ Style/InverseMethods:
316
+ Exclude:
317
+ - 'app/models/sales_invoice.rb'
318
+ - 'app/validators/bank_symbol_validator.rb'
319
+
320
+ # Offense count: 2
321
+ Style/MultilineBlockChain:
322
+ Exclude:
323
+ - 'app/controllers/contracts/most_used_controller.rb'
324
+
325
+ # Offense count: 1
326
+ # Cop supports --auto-correct.
327
+ Style/MultilineIfModifier:
328
+ Exclude:
329
+ - 'app/services/currency_exchange.rb'
330
+
331
+ # Offense count: 2
332
+ Style/MultipleComparison:
333
+ Exclude:
334
+ - 'app/helpers/report_helper.rb'
335
+ - 'lib/core_ext/date.rb'
336
+
337
+ # Offense count: 134
338
+ # Cop supports --auto-correct.
339
+ Style/MutableConstant:
340
+ Enabled: false
341
+
342
+ # Offense count: 4
343
+ # Cop supports --auto-correct.
344
+ Style/NestedParenthesizedCalls:
345
+ Exclude:
346
+ - 'app/controllers/contacts_controller.rb'
347
+ - 'app/decorators/concerns/document_addresses.rb'
348
+ - 'app/models/purchase_order.rb'
349
+ - 'app/services/logo_upload.rb'
350
+
351
+ # Offense count: 1
352
+ # Cop supports --auto-correct.
353
+ # Configuration parameters: EnforcedOctalStyle, SupportedOctalStyles.
354
+ # SupportedOctalStyles: zero_with_o, zero_only
355
+ Style/NumericLiteralPrefix:
356
+ Exclude:
357
+ - 'spec/factories/bank_payments.rb'
358
+
359
+ # Offense count: 14
360
+ # Cop supports --auto-correct.
361
+ # Configuration parameters: Strict.
362
+ Style/NumericLiterals:
363
+ MinDigits: 11
364
+
365
+ # Offense count: 35
366
+ # Cop supports --auto-correct.
367
+ # Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
368
+ # SupportedStyles: predicate, comparison
369
+ Style/NumericPredicate:
370
+ Enabled: false
371
+
372
+ # Offense count: 1
373
+ # Cop supports --auto-correct.
374
+ # Configuration parameters: AllowSafeAssignment.
375
+ Style/ParenthesesAroundCondition:
376
+ Exclude:
377
+ - 'app/models/default_attrs/purchase_invoice.rb'
378
+
379
+ # Offense count: 101
380
+ # Cop supports --auto-correct.
381
+ # Configuration parameters: PreferredDelimiters.
382
+ Style/PercentLiteralDelimiters:
383
+ Enabled: false
384
+
385
+ # Offense count: 10
386
+ # Cop supports --auto-correct.
387
+ Style/RedundantParentheses:
388
+ Exclude:
389
+ - 'app/controllers/application_controller.rb'
390
+ - 'app/models/cash_book_report.rb'
391
+ - 'app/models/concerns/cost_revenue_report_base.rb'
392
+ - 'app/models/contract_report.rb'
393
+ - 'app/models/costs_by_contacts_report.rb'
394
+ - 'app/models/purchase_invoice_item.rb'
395
+ - 'app/queries/query/receivables_core.rb'
396
+ - 'spec/models/external_notification_spec.rb'
397
+
398
+ # Offense count: 3
399
+ # Cop supports --auto-correct.
400
+ # Configuration parameters: AllowMultipleReturnValues.
401
+ Style/RedundantReturn:
402
+ Exclude:
403
+ - 'app/data_objects/interval.rb'
404
+
405
+ # Offense count: 44
406
+ # Cop supports --auto-correct.
407
+ # Configuration parameters: ConvertCodeThatCanStartToReturnNil.
408
+ Style/SafeNavigation:
409
+ Enabled: false
410
+
411
+ # Offense count: 55
412
+ # Cop supports --auto-correct.
413
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
414
+ # SupportedStyles: only_raise, only_fail, semantic
415
+ Style/SignalException:
416
+ Enabled: false
417
+
418
+ # Offense count: 1
419
+ # Cop supports --auto-correct.
420
+ # Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
421
+ # SupportedStyles: single_quotes, double_quotes
422
+ Style/StringLiterals:
423
+ Exclude:
424
+ - 'spec/models/invitation_spec.rb'
425
+
426
+ # Offense count: 160
427
+ # Cop supports --auto-correct.
428
+ # Configuration parameters: EnforcedStyle, MinSize, SupportedStyles.
429
+ # SupportedStyles: percent, brackets
430
+ Style/SymbolArray:
431
+ Enabled: false
432
+
433
+ # Offense count: 5
434
+ # Cop supports --auto-correct.
435
+ Style/UnneededInterpolation:
436
+ Exclude:
437
+ - 'app/helpers/select_helper.rb'
438
+ - 'app/mailers/notification_mailer.rb'
439
+ - 'app/models/user.rb'
440
+ - 'app/services/frontend_params_normalizer.rb'
441
+ - 'spec/features/sales/orders/order_spec.rb'
442
+
443
+ # Offense count: 43
444
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
445
+ # SupportedStyles: snake_case, normalcase, non_integer
446
+ Style/VariableNumber:
447
+ Exclude:
448
+ - 'spec/api/v1/sales_orders_spec.rb'
449
+ - 'spec/features/purchase/invoices_spec.rb'
450
+ - 'spec/features/purchase/petty_cash_disburstment_spec.rb'
451
+ - 'spec/features/sales/orders/order_spec.rb'
452
+ - 'spec/features/sales/petty_cash_income_spec.rb'
453
+ - 'spec/queries/query/cash_book_spec.rb'
454
+ - 'spec/queries/query/contracts_costs_report_spec.rb'
455
+ - 'spec/queries/query/contracts_revenues_report_spec.rb'
456
+ - 'spec/services/cash_book_data_generator_spec.rb'
457
+ - 'spec/services/generate_order_from_confirmed_payments_service_spec.rb'
458
+
459
+ # Offense count: 1
460
+ # Cop supports --auto-correct.
461
+ Style/YodaCondition:
462
+ Exclude:
463
+ - 'app/services/subject_to_vat_specification.rb'
data/Dockerfile ADDED
@@ -0,0 +1,18 @@
1
+ FROM landovsky/ruby:2.4.0
2
+
3
+ ## alias musi byt v .bashrc
4
+ RUN echo '---' > ~/.gemrc \
5
+ && echo 'gem: --no-document' >> ~/.gemrc
6
+
7
+ ENV APPDIR /sipo
8
+ RUN mkdir $APPDIR
9
+ WORKDIR $APPDIR
10
+
11
+ ENV BUNDLE_JOBS=2 \
12
+ BUNDLE_PATH=/gems \
13
+ # do GEM_PATHS se musí přidat cesta z gem_storu
14
+ GEM_PATH=$GEM_PATH:/gems \
15
+ #PATH=$PATH:/gems/bin:/sipo/bin
16
+ PATH=$PATH:/gems/bin
17
+
18
+ ADD . .
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in blender.gemspec
4
+ gem 'pry'
5
+ gem 'rspec'
6
+ gem 'bundler'
7
+ gem 'mail'
8
+ gem 'dry-types'
9
+ gem 'dry-struct'
10
+ gem 'dry-validation'
data/Gemfile.lock ADDED
@@ -0,0 +1,75 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ coderay (1.1.2)
5
+ concurrent-ruby (1.0.5)
6
+ diff-lcs (1.3)
7
+ dry-configurable (0.7.0)
8
+ concurrent-ruby (~> 1.0)
9
+ dry-container (0.6.0)
10
+ concurrent-ruby (~> 1.0)
11
+ dry-configurable (~> 0.1, >= 0.1.3)
12
+ dry-core (0.4.2)
13
+ concurrent-ruby (~> 1.0)
14
+ dry-equalizer (0.2.0)
15
+ dry-logic (0.4.2)
16
+ dry-container (~> 0.2, >= 0.2.6)
17
+ dry-core (~> 0.2)
18
+ dry-equalizer (~> 0.2)
19
+ dry-struct (0.4.0)
20
+ dry-core (~> 0.4, >= 0.4.1)
21
+ dry-equalizer (~> 0.2)
22
+ dry-types (~> 0.12, >= 0.12.2)
23
+ ice_nine (~> 0.11)
24
+ dry-types (0.12.2)
25
+ concurrent-ruby (~> 1.0)
26
+ dry-configurable (~> 0.1)
27
+ dry-container (~> 0.3)
28
+ dry-core (~> 0.2, >= 0.2.1)
29
+ dry-equalizer (~> 0.2)
30
+ dry-logic (~> 0.4, >= 0.4.2)
31
+ inflecto (~> 0.0.0, >= 0.0.2)
32
+ dry-validation (0.11.1)
33
+ concurrent-ruby (~> 1.0)
34
+ dry-configurable (~> 0.1, >= 0.1.3)
35
+ dry-core (~> 0.2, >= 0.2.1)
36
+ dry-equalizer (~> 0.2)
37
+ dry-logic (~> 0.4, >= 0.4.0)
38
+ dry-types (~> 0.12.0)
39
+ ice_nine (0.11.2)
40
+ inflecto (0.0.2)
41
+ mail (2.7.0)
42
+ mini_mime (>= 0.1.1)
43
+ method_source (0.9.0)
44
+ mini_mime (1.0.0)
45
+ pry (0.11.3)
46
+ coderay (~> 1.1.0)
47
+ method_source (~> 0.9.0)
48
+ rspec (3.7.0)
49
+ rspec-core (~> 3.7.0)
50
+ rspec-expectations (~> 3.7.0)
51
+ rspec-mocks (~> 3.7.0)
52
+ rspec-core (3.7.1)
53
+ rspec-support (~> 3.7.0)
54
+ rspec-expectations (3.7.0)
55
+ diff-lcs (>= 1.2.0, < 2.0)
56
+ rspec-support (~> 3.7.0)
57
+ rspec-mocks (3.7.0)
58
+ diff-lcs (>= 1.2.0, < 2.0)
59
+ rspec-support (~> 3.7.0)
60
+ rspec-support (3.7.0)
61
+
62
+ PLATFORMS
63
+ ruby
64
+
65
+ DEPENDENCIES
66
+ bundler
67
+ dry-struct
68
+ dry-types
69
+ dry-validation
70
+ mail
71
+ pry
72
+ rspec
73
+
74
+ BUNDLED WITH
75
+ 1.16.1
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift 'lib'
4
+
5
+ require 'sipo_mailer'
6
+ require 'pry'
7
+
8
+ Pry.start
data/bin/mailer ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift 'lib'
4
+
5
+ require 'pry'
6
+
7
+ require 'sipo_mailer'
8
+
9
+ SipoMailer.perform
@@ -0,0 +1,4 @@
1
+ address_book: /sipo/spec/fixtures/adresar.csv
2
+ email:
3
+ address: @gmail.com
4
+ password:
@@ -0,0 +1,19 @@
1
+ version: "2"
2
+
3
+ volumes:
4
+ gem_store_240:
5
+ external: true
6
+
7
+ services:
8
+ web:
9
+ #image: web:ruby
10
+ build:
11
+ context: .
12
+ command: bash
13
+ env_file: .env
14
+ tty: true
15
+ stdin_open: true
16
+ volumes:
17
+ - gem_store_240:/gems
18
+ - /Users/landovsky/git/sipo:/sipo
19
+ - /Users/landovsky/git/sipo/docs:/docs
@@ -0,0 +1,51 @@
1
+ require 'yaml'
2
+ require 'sipo_mailer/utils/hash_extensions'
3
+
4
+ module SipoMailer
5
+ class Config
6
+ class ConfigMissing < StandardError; end
7
+
8
+ using HashExtensions
9
+
10
+ attr_accessor :yaml
11
+
12
+ def initialize
13
+ Installer.install unless File.exist? Installer.config
14
+ load_yaml
15
+ check_config
16
+ mailer_init
17
+ end
18
+
19
+ private
20
+
21
+ def check_config
22
+ raise ConfigMissing, 'address_book' unless yaml[:address_book]
23
+ raise ConfigMissing, 'email: address' unless yaml.dig(:email, :address)
24
+ raise ConfigMissing, 'email: password' unless yaml.dig(:email, :password)
25
+ rescue ConfigMissing => e
26
+ puts "V konfiguraci není vyplěna hodnota '#{e.message}'. Umístění konfigurace: #{SipoMailer::Installer.config}"
27
+ exit
28
+ end
29
+
30
+ def load_yaml
31
+ self.yaml = YAML.load_file(Installer.config).symbolize_keys
32
+ end
33
+
34
+ def mailer_init
35
+ options = email_options
36
+ Mail.defaults { delivery_method :smtp, options }
37
+ end
38
+
39
+ def email_options
40
+ {
41
+ address: 'smtp.gmail.com',
42
+ port: 587,
43
+ domain: 'gmail.com',
44
+ user_name: 'givit.cz@gmail.com',
45
+ password: yaml.dig(:email, :password),
46
+ authentication: :login,
47
+ enable_starttls_auto: true
48
+ }
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,73 @@
1
+ module SipoMailer
2
+ class Mailer
3
+ class DeliveryError < StandardError
4
+ end
5
+
6
+ class Response
7
+ attr_reader :response
8
+ def initialize(response = nil)
9
+ @response = response
10
+ end
11
+
12
+ def sent?
13
+ if @response.is_a? Mail::Message
14
+ @response&.errors.empty?
15
+ else
16
+ false
17
+ end
18
+ end
19
+ end
20
+
21
+ def initialize(to:, from:, subject:, attachment: nil)
22
+ @to = to
23
+ @from = from
24
+ @subject = subject
25
+ @attachment = attachment
26
+ end
27
+
28
+ def self.send(to: 'landovsky@gmail.com',
29
+ from: SipoMailer.config.yaml.dig(:email, :address),
30
+ subject: 'ahoj',
31
+ attachment: nil)
32
+ email = new(to: to, from: from, subject: subject, attachment: attachment)
33
+ begin
34
+ response = email.send
35
+ Response.new(response)
36
+ rescue DeliveryError => e
37
+ p e
38
+ end
39
+ end
40
+
41
+ def send
42
+ email.deliver!
43
+ rescue SocketError
44
+ print "\n\nChyba při posílání emailu: adresa " \
45
+ "#{Mail.delivery_method.settings[:address]} není dostupná.\n"
46
+ exit
47
+ rescue Net::SMTPAuthenticationError
48
+ print "\n\nChyba při posílání emailu: " \
49
+ "chybné přihlašovací údaje pro emailovou schránku.\n"
50
+ exit
51
+ rescue Net::OpenTimeout
52
+ print "\n\nChyba při posílání emailu: vypršel časový limit "\
53
+ "při spojení s emailovým serverem.\n"
54
+ exit
55
+ end
56
+
57
+ def email
58
+ email = Mail.new
59
+ email.to = @to
60
+ email.from = @from
61
+ email.subject = @subject
62
+ email.body = email_body
63
+ email.add_file(@attachment.path) if @attachment
64
+ email
65
+ end
66
+
67
+ private
68
+
69
+ def email_body
70
+ 'something simple'
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,90 @@
1
+ # Description
2
+ module SipoMailer
3
+ module Models
4
+ class AddressBook
5
+ attr_reader :contacts, :book
6
+
7
+ def initialize
8
+ @file = load_book
9
+ @contacts = without_dups
10
+ end
11
+
12
+ def self.find(id)
13
+ new.find(id)
14
+ end
15
+
16
+ def find(id)
17
+ find_all(id).first
18
+ end
19
+
20
+ private
21
+
22
+ def find_all(id)
23
+ @contacts.select { |c| c.id == id.to_s }
24
+ end
25
+
26
+ def without_dups
27
+ contacts = read_book
28
+ ids = contacts.map(&:id)
29
+ dups = ids.select { |id| ids.count(id) > 1 }.uniq
30
+ return contacts if dups.empty?
31
+
32
+ print "Duplicitní kontakty nebudou zpracovány:\n"
33
+ dups.each do |dup_id|
34
+ contacts.each do |contact|
35
+ printf(" %s: %s\n", contact.id, contact.email) if contact.id == dup_id
36
+ end
37
+ end
38
+
39
+ contacts.reject { |contact| dups.include?(contact.id) }
40
+ end
41
+
42
+ def load_book
43
+ file = SipoMailer.config.yaml[:address_book]
44
+ if file.nil?
45
+ print "Do nastavení dejte cestu k CSV souboru adresáře.\n"
46
+ exit
47
+ end
48
+ open(file)
49
+ rescue Errno::ENOENT
50
+ print "Soubor #{file} nelze otevřít. Máte správně nastavenou cestu?\n"
51
+ exit
52
+ end
53
+
54
+ def parse_contacts(header, book)
55
+ hashes = book.map { |contact| header.zip contact }.map(&:to_h)
56
+ hashes.map do |contact|
57
+ params = symbolize_keys(contact)
58
+ if Models::Contact.valid?(params)
59
+ Models::Contact.new(params)
60
+ else
61
+ row = contact.values.compact.join(', ')
62
+ print "Nepodařilo se zpracovat řádku adresáře: #{row}. "\
63
+ "Je správně oddělen středníkem?\n"
64
+ next
65
+ end
66
+ end.compact
67
+ end
68
+
69
+ def symbolize_keys(hsh)
70
+ {}.tap do |new_hash|
71
+ hsh.each_pair do |key, value|
72
+ new_hash[key.to_sym] = value
73
+ end
74
+ end
75
+ end
76
+
77
+ def read_book
78
+ book = []
79
+ File.open(@file, 'r') do |f|
80
+ f.each_line do |line|
81
+ book << line.delete("\n").split(';')
82
+ end
83
+ end
84
+ header = book[0]
85
+ book = book[1..-1]
86
+ parse_contacts(header, book)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,36 @@
1
+ module SipoMailer
2
+ module Models
3
+ class Attachment
4
+ FILENAME_REGEX = /^[0-9]+_?([0-9]{4}-[0-9]{2}-[0-9]{2})?\.[a-zA-Z0-9]+$/
5
+
6
+ attr_reader :path, :id, :file, :filename, :processed_on
7
+
8
+ def initialize(filename)
9
+ @path = filename
10
+ @file = open(filename)
11
+ parse_meta
12
+ end
13
+
14
+ def valid?
15
+ !(@filename =~ FILENAME_REGEX).nil?
16
+ end
17
+
18
+ def processed?
19
+ !@processed_on.nil?
20
+ end
21
+
22
+ def process; end
23
+
24
+ private
25
+
26
+ def parse_meta
27
+ @filename = @file.path.split('/').last
28
+ name = @filename.split('.').first
29
+ try_date = name.split('_')
30
+
31
+ @id = try_date.first
32
+ @processed_on = try_date.last if try_date.size == 2
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ require 'sipo_mailer/models/types'
2
+
3
+ module SipoMailer
4
+ module Models
5
+ class Contact < Dry::Struct
6
+ constructor_type :strict
7
+
8
+ attribute :cislo, Types::String
9
+ attribute :email, Types::String
10
+
11
+ def id
12
+ cislo
13
+ end
14
+
15
+ def self.valid?(params)
16
+ schema = Dry::Validation.Schema do
17
+ required(:cislo).filled
18
+ required(:email).filled
19
+ end
20
+
21
+ schema.call(params).errors.empty?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module SipoMailer
2
+ module Models
3
+ module Types
4
+ include Dry::Types.module
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,39 @@
1
+ module HashExtensions
2
+ refine Hash do
3
+ def transform_keys
4
+ result = {}
5
+ each_key do |key|
6
+ result[yield(key)] = self[key]
7
+ end
8
+ result
9
+ end
10
+
11
+ def symbolize_keys
12
+ symbolized = {}
13
+ each do |key, value|
14
+ new_key = key.to_sym rescue key
15
+ new_val = if value.is_a? Hash
16
+ value.symbolize_keys
17
+ else
18
+ value
19
+ end
20
+ symbolized[new_key] = new_val
21
+ end
22
+ symbolized
23
+ end
24
+
25
+ def stringify_values
26
+ transformed = dup
27
+ transformed.each do |key, value|
28
+ new_val = if value.is_a? Hash
29
+ value
30
+ elsif value.is_a? Array
31
+ value
32
+ else
33
+ value.to_s
34
+ end
35
+ transformed[key] = new_val
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,56 @@
1
+ module SipoMailer
2
+ module Installer
3
+ DEFAULT_DIR = 'sipo_mailer'.freeze
4
+ CONFIG_FILE = 'config.yml'
5
+
6
+ class << self
7
+ def install
8
+ create_dir ? copy_config : nil
9
+ end
10
+
11
+ def create_dir
12
+ result = Dir.mkdir(config_dir) unless Dir.exist?(config_dir)
13
+ result == 0
14
+ end
15
+
16
+ def copy_config
17
+ return false if File.exist? config
18
+ File.open("#{config_dir}/#{CONFIG_FILE}", 'w') do |file|
19
+ example = File.open("config/#{CONFIG_FILE}.example")
20
+ file.write(example.readlines.join(''))
21
+ example.close
22
+ end
23
+ true
24
+ end
25
+
26
+ def config
27
+ [config_dir, CONFIG_FILE].join('/')
28
+ end
29
+
30
+ def config_dir
31
+ case os
32
+ when :windows
33
+ [ENV['HOME'], DEFAULT_DIR].join('/')
34
+ else
35
+ [ENV['USERPROFILE'], DEFAULT_DIR].join('/')
36
+ end
37
+ end
38
+
39
+ def os
40
+ host_os = RbConfig::CONFIG['host_os']
41
+ case host_os
42
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
43
+ :windows
44
+ when /darwin|mac os/
45
+ :macosx
46
+ when /linux/
47
+ :linux
48
+ when /solaris|bsd/
49
+ :unix
50
+ else
51
+ raise Error::WebDriverError, "unknown os: #{host_os.inspect}"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,22 @@
1
+ # Test
2
+ module SipoMailer
3
+ class Testik
4
+ class Con
5
+ def initialize
6
+ init
7
+ @con = 1
8
+ end
9
+
10
+ def init
11
+ end
12
+ end
13
+
14
+ @config ||= Con.new
15
+
16
+ class << self
17
+ def con
18
+ @config
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module SipoMailer
2
+ class Timer
3
+ def self.elapsed(&block)
4
+ start = Time.now
5
+ yield(block)
6
+ finish = Time.now
7
+ e = (finish - start) * 1000
8
+ p "Elapsed time: #{e} ms"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## TODOs
4
+ # zpracovane prejmenovat
5
+
6
+ require 'pry'
7
+ require 'mail'
8
+ require 'dry-types'
9
+ require 'dry-struct'
10
+ require 'dry-validation'
11
+
12
+ $LOAD_PATH.unshift __dir__
13
+ Dir["#{__dir__}/**/*.rb"].each { |file| require file }
14
+
15
+ module SipoMailer
16
+ class << self
17
+ attr_accessor :config, :address_book
18
+ end
19
+
20
+ @config ||= Config.new
21
+ @address_book ||= Models::AddressBook.new
22
+
23
+ def self.perform
24
+ files = Dir[Dir.pwd + '/*.*']
25
+ files = files.map { |path| Models::Attachment.new(path) }.select(&:valid?)
26
+ files = files.reject { |file| file.processed? }
27
+
28
+ if files.none?
29
+ printf "Žádné soubory ke zpracování\n"
30
+ exit
31
+ end
32
+
33
+ printf "Našel jsem %d souborů ke zpracování.\n\n", files.count
34
+
35
+ files = files.reject do |file|
36
+ if SipoMailer.address_book.find(file.id).nil?
37
+ printf "Vyřazuji soubor #{file.filename}, číslo #{file.id} nenalezeno v adresáři.\n\n"
38
+ true
39
+ else
40
+ false
41
+ end
42
+ end
43
+
44
+ response = nil
45
+ until %w(a n).include?(response)
46
+ printf "Poslat %s soubor/ů?\n", files.count
47
+ print "(a) ano\n"
48
+ print "(n) ne\n"
49
+
50
+ response = STDIN.gets.strip
51
+ exit if response == 'n'
52
+ system('clear')
53
+ end
54
+
55
+ files.each do |file|
56
+ to = SipoMailer.address_book.find(file.id).email
57
+ printf 'Posílám soubor %s na %s', file.filename, to
58
+
59
+ email = Mailer.send(to: to, attachment: file)
60
+ printf " ok\n\n" if email.sent?
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'sipo_mailer'
3
+ s.version = '0.0.1'
4
+ s.summary = 'Command-line aplikace na odesílání souborů jako příloh na email dle CSV adresáře.'
5
+ s.author = 'Tomáš Landovský'
6
+ s.email = 'landovsky@gmail.com'
7
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
8
+ f.match(%r{^(tmp|test|spec|features)/})
9
+ end
10
+ s.homepage = 'http://rubygems.org/gems/sipo_mailer'
11
+ s.license = 'MIT'
12
+ s.bindir = 'bin'
13
+ s.executables = 'mailer'
14
+
15
+ s.add_development_dependency 'bundler'
16
+ s.add_development_dependency 'pry'
17
+ s.add_development_dependency 'rspec'
18
+
19
+ s.add_runtime_dependency 'dry-struct'
20
+ s.add_runtime_dependency 'dry-types'
21
+ s.add_runtime_dependency 'dry-validation'
22
+ s.add_runtime_dependency 'mail'
23
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sipo_mailer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tomáš Landovský
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dry-struct
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dry-types
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: dry-validation
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mail
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email: landovsky@gmail.com
113
+ executables:
114
+ - mailer
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rubocop.yml"
120
+ - ".rubocop_todo.yml"
121
+ - Dockerfile
122
+ - Gemfile
123
+ - Gemfile.lock
124
+ - bin/console
125
+ - bin/mailer
126
+ - config/config.yml.example
127
+ - docker-compose.yml
128
+ - lib/sipo_mailer.rb
129
+ - lib/sipo_mailer/config.rb
130
+ - lib/sipo_mailer/email.rb
131
+ - lib/sipo_mailer/models/address_book.rb
132
+ - lib/sipo_mailer/models/attachment.rb
133
+ - lib/sipo_mailer/models/contact.rb
134
+ - lib/sipo_mailer/models/types.rb
135
+ - lib/sipo_mailer/utils/hash_extensions.rb
136
+ - lib/sipo_mailer/utils/installer.rb
137
+ - lib/sipo_mailer/utils/testik.rb
138
+ - lib/sipo_mailer/utils/timer.rb
139
+ - sipo_mailer.gemspec
140
+ homepage: http://rubygems.org/gems/sipo_mailer
141
+ licenses:
142
+ - MIT
143
+ metadata: {}
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 2.6.8
161
+ signing_key:
162
+ specification_version: 4
163
+ summary: Command-line aplikace na odesílání souborů jako příloh na email dle CSV adresáře.
164
+ test_files: []