├── .env_sample ├── twilio_sendgrid_logo.png ├── static └── img │ ├── github-fork.png │ └── github-sign-up.png ├── test ├── test_helper.rb └── test.rb ├── Gemfile ├── lib ├── smtpapi │ └── version.rb └── smtpapi.rb ├── Makefile ├── USAGE.md ├── Rakefile ├── .gitignore ├── use_cases └── README.md ├── .github └── workflows │ ├── pr-lint.yml │ └── test-and-deploy.yml ├── TROUBLESHOOTING.md ├── .rubocop.yml ├── smtpapi.gemspec ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── examples └── example.rb ├── .rubocop_todo.yml ├── FIRST_TIMERS.md ├── README.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md └── CHANGELOG.md /.env_sample: -------------------------------------------------------------------------------- 1 | SENDGRID_API_KEY= -------------------------------------------------------------------------------- /twilio_sendgrid_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/smtpapi-ruby/HEAD/twilio_sendgrid_logo.png -------------------------------------------------------------------------------- /static/img/github-fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/smtpapi-ruby/HEAD/static/img/github-fork.png -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | if RUBY_VERSION.equal?('2.7') 2 | require 'simplecov' 3 | SimpleCov.start 4 | end 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in smtpapi.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/smtpapi/version.rb: -------------------------------------------------------------------------------- 1 | # 2 | # SendGrid smtpapi 3 | # 4 | module Smtpapi 5 | VERSION = '0.1.12'.freeze 6 | end 7 | -------------------------------------------------------------------------------- /static/img/github-sign-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/smtpapi-ruby/HEAD/static/img/github-sign-up.png -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: install test 2 | 3 | install: 4 | gem install bundler:1.14.6; bundle install 5 | 6 | test: 7 | rake test 8 | -------------------------------------------------------------------------------- /USAGE.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | - [SendGrid Docs](https://sendgrid.com/docs/API_Reference/SMTP_API/index.html) 4 | - [Example Code](examples) 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rake/testtask' 3 | 4 | Rake::TestTask.new do |t| 5 | t.libs << 'test' 6 | t.test_files = FileList['test/test*.rb'] 7 | t.verbose = true 8 | end 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | .env -------------------------------------------------------------------------------- /use_cases/README.md: -------------------------------------------------------------------------------- 1 | This directory provides examples for specific use cases. Please [open an issue](https://github.com/sendgrid/smtpapi-ruby/issues) or make a pull request for any use cases you would like us to document here. Thank you! 2 | 3 | # Table of Contents 4 | -------------------------------------------------------------------------------- /.github/workflows/pr-lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint PR 2 | on: 3 | pull_request_target: 4 | types: [ opened, edited, synchronize, reopened ] 5 | 6 | jobs: 7 | validate: 8 | name: Validate title 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: amannn/action-semantic-pull-request@v4 12 | with: 13 | types: chore docs fix feat test misc 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /TROUBLESHOOTING.md: -------------------------------------------------------------------------------- 1 | If you have a SendGrid issue, please contact our [support team](https://support.sendgrid.com). 2 | 3 | ## Table of Contents 4 | * [Viewing the Request Header](#request-header) 5 | 6 | 7 | ## Viewing the Request Header 8 | 9 | When debugging or testing, it may be useful to examine the raw request header to compare against the [documented format](https://sendgrid.com/docs/API_Reference/api_v3.html). 10 | 11 | You can do this like so: 12 | 13 | ```ruby 14 | puts header 15 | ``` 16 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | # Allow "set_" and "get_" for prefix of method 4 | AccessorMethodName: 5 | Enabled: false 6 | 7 | # Increase max line number of method 8 | MethodLength: 9 | CountComments: true # count full line comments? 10 | Max: 20 11 | 12 | # Increase the number of params 13 | ParameterLists: 14 | Max: 6 15 | CountKeywordArgs: true 16 | 17 | # Increase the max AbcSize 18 | AbcSize: 19 | Max: 34 20 | 21 | # Increase the max line number of class 22 | ClassLength: 23 | Max: 250 24 | CountComments: true 25 | 26 | CyclomaticComplexity: 27 | Max: 12 28 | 29 | PerceivedComplexity: 30 | Max: 12 31 | 32 | Metrics/LineLength: 33 | Max: 100 -------------------------------------------------------------------------------- /smtpapi.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path('lib', __dir__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | require 'smtpapi/version' 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = 'smtpapi' 7 | spec.version = Smtpapi::VERSION 8 | spec.authors = ['Wataru Sato', 'SendGrid'] 9 | spec.email = ['awwa500@gmail.com', 'community@sendgrid.com'] 10 | spec.summary = 'Smtpapi library for SendGrid.' 11 | spec.description = 'Smtpapi library for SendGrid.' 12 | spec.homepage = 'https://github.com/sendgrid/smtpapi-ruby' 13 | spec.license = 'MIT' 14 | 15 | spec.files = `git ls-files -z`.split("\x0") 16 | spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) } 17 | spec.test_files = spec.files.grep(/^(test|spec|features)/) 18 | spec.require_paths = ['lib'] 19 | 20 | spec.add_development_dependency 'rake' 21 | spec.add_development_dependency('test-unit', '~> 3.0') 22 | spec.add_development_dependency('simplecov', '~> 0.18.5') 23 | end 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2023, Twilio SendGrid, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | # Fixes # 18 | 19 | A short description of what this PR does. 20 | 21 | ### Checklist 22 | - [x] I acknowledge that all my contributions will be made under the project's license 23 | - [ ] I have made a material change to the repo (functionality, testing, spelling, grammar) 24 | - [ ] I have read the [Contribution Guidelines](https://github.com/sendgrid/smtpapi-ruby/blob/main/CONTRIBUTING.md) and my PR follows them 25 | - [ ] I have titled the PR appropriately 26 | - [ ] I have updated my branch with the main branch 27 | - [ ] I have added tests that prove my fix is effective or that my feature works 28 | - [ ] I have added the necessary documentation about the functionality in the appropriate .md file 29 | - [ ] I have added inline documentation to the code I modified 30 | 31 | If you have questions, please file a [support ticket](https://support.sendgrid.com), or create a GitHub Issue in this repository. 32 | -------------------------------------------------------------------------------- /examples/example.rb: -------------------------------------------------------------------------------- 1 | require_relative '../lib/smtpapi' 2 | header = Smtpapi::Header.new 3 | 4 | ## add_to 5 | header.add_to('test1@example.com') 6 | header.add_to('test2@example.com', 'other') 7 | # header.add_to(['test1@example.com', 'test2@example.com']) 8 | 9 | ## set_tos 10 | # header.set_tos(['you@youremail.com', 'other@otheremail.com']) 11 | # to => ['you@youremail.com', 'other@otheremail.com'] 12 | 13 | ## add_substitution 14 | # sub = {keep: ['secret']} 15 | header.add_substitution('keep', ['secret']) 16 | # sub = {keep: ['secret'], other: ['one', 'two']} 17 | header.add_substitution('other', %w(one two)) 18 | 19 | ## set_substitutions 20 | # header.set_substitutions({'keep' => 'secret'}) # sub = {keep: ['secret']} 21 | 22 | ## add_unique_arg 23 | header.add_unique_arg('cat', 'dogs') 24 | 25 | ## set_unique_args 26 | # header.set_unique_args({'cow' => 'chicken'}) 27 | # header.set_unique_args({'dad' => 'proud'}) 28 | 29 | ## add_category 30 | # category = ['tactics'] 31 | header.add_category('tactics') 32 | # category = ['tactics', 'advanced'] 33 | header.add_category('advanced') 34 | 35 | ## set_categories 36 | # category = ['tactics', 'advanced'] 37 | # header.set_categories(['tactics', 'advanced']) 38 | 39 | ## add_section 40 | header.add_section('-charge-', 'This ship is useless.') 41 | header.add_section('-bomber-', 'Only for sad vikings.') 42 | 43 | ## set_sections 44 | # header.set_sections({'-charge-' => 'This ship is useless.'}) 45 | 46 | ## add_filter 47 | header.add_filter('footer', 'enable', 1) 48 | header.add_filter('footer', 'text/html', 'boo') 49 | 50 | ## set_filters 51 | # filter = { 52 | # 'footer' => { 53 | # 'setting' => { 54 | # 'enable' => 1, 55 | # "text/plain" => 'You can haz footers!' 56 | # } 57 | # } 58 | # } 59 | # header.set_filters(filter) 60 | 61 | ## set_send_at 62 | lt = Time.local(2014, 8, 29, 17, 56, 35) 63 | header.set_send_at(lt) 64 | 65 | ## set_send_each_at 66 | # lt1 = Time.local(2014, 8, 29, 17, 56, 35) 67 | # lt2 = Time.local(2013, 12, 31, 0, 0, 0) 68 | # lt3 = Time.local(2015, 9, 1, 4, 5, 6) 69 | # header.set_send_each_at([lt1, lt2, lt3]) 70 | 71 | ## asm_group_id 72 | # This is to specify an ASM Group for the message. 73 | # See: https://sendgrid.com/docs/User_Guide/advanced_suppression_manager.html 74 | header.set_asm_group(2) 75 | 76 | ## set_ip_pool 77 | # Using IP Pools with the SMTP API Header 78 | # See: https://sendgrid.com/docs/API_Reference/Web_API_v3/IP_Management/ip_pools.html) 79 | header.set_ip_pool('test_pool') 80 | 81 | print header.to_json 82 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2022-01-25 23:22:53 UTC using RuboCop version 1.22.2. 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: 1 10 | # Cop supports --auto-correct. 11 | # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. 12 | # Include: **/*.gemspec 13 | Gemspec/OrderedDependencies: 14 | Exclude: 15 | - 'smtpapi.gemspec' 16 | 17 | # Offense count: 1 18 | # Configuration parameters: Include. 19 | # Include: **/*.gemspec 20 | Gemspec/RequiredRubyVersion: 21 | Exclude: 22 | - 'smtpapi.gemspec' 23 | 24 | # Offense count: 1 25 | # Cop supports --auto-correct. 26 | # Configuration parameters: EnforcedStyle. 27 | # SupportedStyles: final_newline, final_blank_line 28 | Layout/TrailingEmptyLines: 29 | Exclude: 30 | - 'Gemfile' 31 | 32 | # Offense count: 1 33 | # Configuration parameters: IgnoredMethods. 34 | Metrics/CyclomaticComplexity: 35 | Max: 12 36 | 37 | # Offense count: 1 38 | # Configuration parameters: IgnoredMethods. 39 | Metrics/PerceivedComplexity: 40 | Max: 12 41 | 42 | # Offense count: 2 43 | # Cop supports --auto-correct. 44 | # Configuration parameters: EnforcedStyle. 45 | # SupportedStyles: separated, grouped 46 | Style/AccessorGrouping: 47 | Exclude: 48 | - 'lib/smtpapi.rb' 49 | 50 | # Offense count: 1 51 | # Cop supports --auto-correct. 52 | # Configuration parameters: EnforcedStyle. 53 | # SupportedStyles: prefer_alias, prefer_alias_method 54 | Style/Alias: 55 | Exclude: 56 | - 'lib/smtpapi.rb' 57 | 58 | # Offense count: 8 59 | # Cop supports --auto-correct. 60 | # Configuration parameters: EnforcedStyle. 61 | # SupportedStyles: always, always_true, never 62 | Style/FrozenStringLiteralComment: 63 | Exclude: 64 | - 'Gemfile' 65 | - 'Rakefile' 66 | - 'examples/example.rb' 67 | - 'lib/smtpapi.rb' 68 | - 'lib/smtpapi/version.rb' 69 | - 'smtpapi.gemspec' 70 | - 'test/test.rb' 71 | - 'test/test_helper.rb' 72 | 73 | # Offense count: 1 74 | # Cop supports --auto-correct. 75 | # Configuration parameters: UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. 76 | # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys 77 | Style/HashSyntax: 78 | EnforcedStyle: hash_rockets 79 | 80 | # Offense count: 3 81 | # Cop supports --auto-correct. 82 | # Configuration parameters: PreferredDelimiters. 83 | Style/PercentLiteralDelimiters: 84 | Exclude: 85 | - 'examples/example.rb' 86 | - 'test/test.rb' 87 | 88 | # Offense count: 2 89 | # Cop supports --auto-correct. 90 | # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. 91 | # SupportedStyles: single_quotes, double_quotes 92 | Style/StringLiterals: 93 | Exclude: 94 | - 'Gemfile' 95 | -------------------------------------------------------------------------------- /FIRST_TIMERS.md: -------------------------------------------------------------------------------- 1 | # How To Contribute to Twilio SendGrid Repositories via GitHub 2 | Contributing to the Twilio SendGrid repositories is easy! All you need to do is find an open issue (see the bottom of this page for a list of repositories containing open issues), fix it and submit a pull request. Once you have submitted your pull request, the team can easily review it before it is merged into the repository. 3 | 4 | To make a pull request, follow these steps: 5 | 6 | 1. Log into GitHub. If you do not already have a GitHub account, you will have to create one in order to submit a change. Click the Sign up link in the upper right-hand corner to create an account. Enter your username, password, and email address. If you are an employee of Twilio SendGrid, please use your full name with your GitHub account and enter Twilio SendGrid as your company so we can easily identify you. 7 | 8 | 9 | 10 | 2. __[Fork](https://help.github.com/fork-a-repo/)__ the [smtpapi-php](https://github.com/sendgrid/smtpapi-php) repository: 11 | 12 | 13 | 14 | 3. __Clone__ your fork via the following commands: 15 | 16 | ```bash 17 | # Clone your fork of the repo into the current directory 18 | git clone https://github.com/your_username/smtpapi-php 19 | # Navigate to the newly cloned directory 20 | cd smtpapi-php 21 | # Assign the original repo to a remote called "upstream" 22 | git remote add upstream https://github.com/sendgrid/smtpapi-php 23 | ``` 24 | 25 | > Don't forget to replace *your_username* in the URL by your real GitHub username. 26 | 27 | 4. __Create a new topic branch__ (off the main project development branch) to contain your feature, change, or fix: 28 | 29 | ```bash 30 | git checkout -b 31 | ``` 32 | 33 | 5. __Commit your changes__ in logical chunks. 34 | 35 | Please adhere to these [git commit message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) or your code is unlikely be merged into the main project. Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public. Probably you will also have to create tests (if needed) or create or update the example code that demonstrates the functionality of this change to the code. 36 | 37 | 6. __Locally merge (or rebase)__ the upstream development branch into your topic branch: 38 | 39 | ```bash 40 | git pull [--rebase] upstream main 41 | ``` 42 | 43 | 7. __Push__ your topic branch up to your fork: 44 | 45 | ```bash 46 | git push origin 47 | ``` 48 | 49 | 8. __[Open a Pull Request](https://help.github.com/articles/creating-a-pull-request/#changing-the-branch-range-and-destination-repository/)__ with a clear title and description against the `main` branch. All tests must be passing before we will review the PR. 50 | 51 | ## Important notice 52 | 53 | Before creating a pull request, make sure that you respect the repository's constraints regarding contributions. You can find them in the [CONTRIBUTING.md](CONTRIBUTING.md) file. 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![SendGrid Logo](twilio_sendgrid_logo.png) 2 | 3 | [![Build Status](https://github.com/sendgrid/smtpapi-ruby/actions/workflows/test-and-deploy.yml/badge.svg)](https://github.com/sendgrid/smtpapi-ruby/actions/workflows/test-and-deploy.yml) 4 | [![Gem Version](https://badge.fury.io/rb/smtpapi.svg)](https://badge.fury.io/rb/smtpapi) 5 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 6 | [![Twitter Follow](https://img.shields.io/twitter/follow/sendgrid.svg?style=social&label=Follow)](https://twitter.com/sendgrid) 7 | [![GitHub contributors](https://img.shields.io/github/contributors/sendgrid/smtpapi-ruby.svg)](https://github.com/sendgrid/smtpapi-ruby/graphs/contributors) 8 | 9 | **This ruby gem allows you to quickly and more easily generate SendGrid X-SMTPAPI headers.** 10 | 11 | # Announcements 12 | All updates to this library is documented in our [CHANGELOG](CHANGELOG.md). 13 | 14 | # Table of Contents 15 | - [Installation](#installation) 16 | - [Quick Start](#quick-start) 17 | - [Usage](#usage) 18 | - [How to Contribute](#contribute) 19 | - [About](#about) 20 | - [Support](#support) 21 | - [License](#license) 22 | 23 | 24 | # Installation 25 | 26 | ## Prerequisites 27 | 28 | - Ruby version >= 2.4 29 | - The SendGrid service, starting at the [free level](https://sendgrid.com/free?source=smtpapi-ruby) 30 | 31 | ## Install Package 32 | 33 | Add this line to your application's Gemfile: 34 | 35 | ```bash 36 | gem 'smtpapi' 37 | ``` 38 | 39 | And then execute: 40 | 41 | ```bash 42 | bundle 43 | ``` 44 | 45 | Or install it yourself as: 46 | 47 | ```bash 48 | gem install smtpapi 49 | ``` 50 | 51 | ## Setup Environment Variables 52 | 53 | ### Environment Variable 54 | 55 | Update the development environment with your [SENDGRID_API_KEY](https://app.sendgrid.com/settings/api_keys), for example: 56 | 57 | ```bash 58 | echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env 59 | echo "sendgrid.env" >> .gitignore 60 | source ./sendgrid.env 61 | ``` 62 | 63 | 64 | # Quick Start 65 | 66 | ```ruby 67 | header = Smtpapi::Header.new 68 | header.add_to('test@example.com') 69 | print header.to_json 70 | ``` 71 | 72 | 73 | # Usage 74 | 75 | - [SendGrid Docs](https://sendgrid.com/docs/API_Reference/SMTP_API/index.html) 76 | - [Example Code](examples) 77 | 78 | 79 | # How to Contribute 80 | 81 | We encourage contribution to our libraries, please see our [CONTRIBUTING](CONTRIBUTING.md) guide for details. 82 | 83 | Quick links: 84 | 85 | - [Improvements to the Codebase](CONTRIBUTING.md#improvements_to_the_codebase) 86 | - [Review Pull Requests](CONTRIBUTING.md#code-reviews) 87 | 88 | ## Credits 89 | 90 | This library was created by [Wataru Sato](https://github.com/awwa) and is now maintained by SendGrid. 91 | 92 | 93 | # About 94 | 95 | smtpapi-ruby is maintained and funded by Twilio SendGrid, Inc. The names and logos for smtpapi-ruby are trademarks of Twilio SendGrid, Inc. 96 | 97 | 98 | # Support 99 | 100 | If you need with SendGrid, please check the [Twilio SendGrid Support Help Center](https://support.sendgrid.com). 101 | 102 | 103 | # License 104 | 105 | [The MIT License (MIT)](LICENSE) 106 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at open-source@twilio.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /.github/workflows/test-and-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Test and Deploy 2 | on: 3 | push: 4 | branches: [ '*' ] 5 | tags: [ '*' ] 6 | pull_request: 7 | branches: [ main ] 8 | schedule: 9 | # Run automatically at 8AM PST Monday-Friday 10 | - cron: '0 15 * * 1-5' 11 | workflow_dispatch: 12 | 13 | jobs: 14 | test: 15 | name: Test 16 | runs-on: ubuntu-latest 17 | timeout-minutes: 20 18 | strategy: 19 | matrix: 20 | ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', 'jruby-9.2' ] 21 | steps: 22 | - name: Checkout smtpapi-ruby 23 | uses: actions/checkout@v2 24 | with: 25 | fetch-depth: 0 26 | 27 | - name: Set up Ruby 28 | uses: ruby/setup-ruby@v1 29 | with: 30 | ruby-version: ${{ matrix.ruby }} 31 | bundler-cache: true 32 | 33 | - run: make install 34 | 35 | - name: Set up linter 36 | run: bundle add rubocop --version "~> 1.24.1" --group "development" --skip-install 37 | if: ${{ matrix.ruby != '2.4' }} 38 | 39 | - run: bundle install --with development && bundle exec rake install 40 | 41 | - name: Run linter 42 | run: bundle exec rubocop 43 | if: ${{ matrix.ruby != '2.4' }} 44 | 45 | - name: Run tests 46 | run: make test 47 | 48 | deploy: 49 | name: Deploy 50 | if: success() && github.ref_type == 'tag' 51 | needs: [ test ] 52 | runs-on: ubuntu-latest 53 | steps: 54 | - name: Checkout smtpapi-ruby 55 | uses: actions/checkout@v2 56 | with: 57 | fetch-depth: 0 58 | 59 | - name: Set up Ruby 60 | uses: ruby/setup-ruby@v1 61 | with: 62 | ruby-version: 3.1 63 | bundler-cache: true 64 | 65 | - run: make install 66 | 67 | - name: Create GitHub Release 68 | uses: sendgrid/dx-automator/actions/release@main 69 | env: 70 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 71 | 72 | - name: Publish to Rubygems 73 | env: 74 | GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }} 75 | run: | 76 | mkdir -p $HOME/.gem 77 | touch $HOME/.gem/credentials 78 | chmod 0600 $HOME/.gem/credentials 79 | printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials 80 | gem build *.gemspec 81 | gem push *.gem 82 | 83 | - name: Submit metric to Datadog 84 | uses: sendgrid/dx-automator/actions/datadog-release-metric@main 85 | env: 86 | DD_API_KEY: ${{ secrets.DATADOG_API_KEY }} 87 | 88 | notify-on-failure: 89 | name: Slack notify on failure 90 | if: failure() && github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag') 91 | needs: [ test, deploy ] 92 | runs-on: ubuntu-latest 93 | steps: 94 | - uses: rtCamp/action-slack-notify@v2 95 | env: 96 | SLACK_COLOR: failure 97 | SLACK_ICON_EMOJI: ':github:' 98 | SLACK_MESSAGE: ${{ format('Test *{0}*, Deploy *{1}*, {2}/{3}/actions/runs/{4}', needs.test.result, needs.deploy.result, github.server_url, github.repository, github.run_id) }} 99 | SLACK_TITLE: Action Failure - ${{ github.repository }} 100 | SLACK_USERNAME: GitHub Actions 101 | SLACK_MSG_AUTHOR: twilio-dx 102 | SLACK_FOOTER: Posted automatically using GitHub Actions 103 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} 104 | MSG_MINIMAL: true 105 | -------------------------------------------------------------------------------- /lib/smtpapi.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.dirname(__FILE__) 2 | require 'smtpapi/version' 3 | require 'json' 4 | 5 | module Smtpapi 6 | # 7 | # SendGrid smtpapi header implementation 8 | # 9 | class Header 10 | attr_reader :to, :sub, :section, :category, :unique_args, :filters 11 | attr_reader :send_at, :send_each_at, :asm_group_id, :ip_pool 12 | 13 | def initialize 14 | @to = [] 15 | @sub = {} 16 | @section = {} 17 | @category = [] 18 | @unique_args = {} 19 | @filters = {} 20 | @send_at = nil 21 | @send_each_at = [] 22 | @asm_group_id = nil 23 | @ip_pool = nil 24 | end 25 | 26 | def add_to(address, name = nil) 27 | if address.is_a?(Array) 28 | @to.concat(address) 29 | else 30 | value = address 31 | value = "#{name} <#{address}>" unless name.nil? 32 | @to.push(value) 33 | end 34 | self 35 | end 36 | 37 | def set_tos(addresses) 38 | @to = addresses 39 | self 40 | end 41 | 42 | def add_substitution(sub, values) 43 | @sub[sub] = values 44 | self 45 | end 46 | 47 | def set_substitutions(key_value_pairs) 48 | @sub = key_value_pairs 49 | self 50 | end 51 | 52 | def add_section(key, value) 53 | @section[key] = value 54 | self 55 | end 56 | 57 | def set_sections(key_value_pairs) 58 | @section = key_value_pairs 59 | self 60 | end 61 | 62 | def add_unique_arg(key, value) 63 | @unique_args[key] = value 64 | self 65 | end 66 | 67 | def set_unique_args(key_value_pairs) 68 | @unique_args = key_value_pairs 69 | self 70 | end 71 | 72 | def add_category(category) 73 | @category.push(category) 74 | self 75 | end 76 | 77 | def set_categories(categories) 78 | @category = categories 79 | self 80 | end 81 | 82 | def add_filter(filter_name, parameter_name, parameter_value) 83 | @filters[filter_name] = {} if @filters[filter_name].nil? 84 | @filters[filter_name]['settings'] = {} if @filters[filter_name]['settings'].nil? 85 | @filters[filter_name]['settings'][parameter_name] = parameter_value 86 | self 87 | end 88 | 89 | def set_filters(filters) 90 | @filters = filters 91 | self 92 | end 93 | 94 | def set_send_at(send_at) 95 | @send_at = send_at 96 | self 97 | end 98 | 99 | def set_send_each_at(send_each_at) 100 | @send_each_at = send_each_at 101 | self 102 | end 103 | 104 | def set_asm_group(group_id) 105 | @asm_group_id = group_id 106 | self 107 | end 108 | 109 | def set_ip_pool(pool_name) 110 | @ip_pool = pool_name 111 | self 112 | end 113 | 114 | def json_string 115 | escape_unicode(to_array.to_json) 116 | end 117 | alias_method :to_json, :json_string 118 | 119 | def escape_unicode(str) 120 | str.unpack('U*').map do |i| 121 | if i > 65_535 122 | "\\u#{format('%04x', ((i - 0x10000) / 0x400 + 0xD800))}" \ 123 | "\\u#{format('%04x', ((i - 0x10000) % 0x400 + 0xDC00))}" 124 | elsif i > 127 125 | "\\u#{format('%04x', i)}" 126 | else 127 | i.chr('UTF-8') 128 | end 129 | end.join 130 | end 131 | 132 | protected 133 | 134 | def to_array 135 | data = {} 136 | data['to'] = @to unless @to.empty? 137 | data['sub'] = @sub unless @sub.empty? 138 | data['section'] = @section unless @section.empty? 139 | data['unique_args'] = @unique_args unless @unique_args.empty? 140 | data['category'] = @category unless @category.empty? 141 | data['filters'] = @filters unless @filters.empty? 142 | data['send_at'] = @send_at.to_i unless @send_at.nil? 143 | data['asm_group_id'] = @asm_group_id.to_i unless @asm_group_id.nil? 144 | data['ip_pool'] = @ip_pool unless @ip_pool.nil? 145 | str_each_at = [] 146 | 147 | @send_each_at.each do |val| 148 | str_each_at.push(val.to_i) 149 | end 150 | 151 | data['send_each_at'] = str_each_at unless str_each_at.empty? 152 | 153 | data 154 | end 155 | end 156 | end 157 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Hello! Thank you for choosing to help contribute to one of the SendGrid open source libraries. There are many ways you can contribute and help is always welcome. We simply ask that you follow the following contribution policies. 2 | 3 | - [Improvements to the Codebase](#improvements-to-the-codebase) 4 | - [Understanding the Code Base](#understanding-the-codebase) 5 | - [Testing](#testing) 6 | - [Style Guidelines & Naming Conventions](#style-guidelines-and-naming-conventions) 7 | - [Creating a Pull Request](#creating-a-pull-request) 8 | - [Code Reviews](#code-reviews) 9 | 10 | 11 | ## Improvements to the Codebase 12 | 13 | We welcome direct contributions to the smtpapi-ruby code base. Thank you! 14 | 15 | ### Development Environment ### 16 | 17 | #### Install and Run Locally #### 18 | 19 | ##### Prerequisites ##### 20 | 21 | - Ruby version 2.2 22 | - The SendGrid Service, starting at the [free level](https://sendgrid.com/free?source=smtpapi-ruby)) 23 | 24 | ##### Initial setup: ##### 25 | 26 | ```bash 27 | git clone https://github.com/sendgrid/smtpapi-ruby.git 28 | cd smtpapi-ruby 29 | ``` 30 | 31 | ##### Execute: ##### 32 | 33 | See the [examples folder](examples) to get started quickly. 34 | 35 | To run the example: 36 | 37 | ```bash 38 | ruby examples/example.rb 39 | ``` 40 | 41 | 42 | ## Understanding the Code Base 43 | 44 | **/examples** 45 | 46 | Working examples that demonstrate usage. 47 | 48 | **/tess** 49 | 50 | Unit tests 51 | 52 | **/lib/smtpapi** 53 | 54 | Source code. 55 | 56 | 57 | ## Testing 58 | 59 | All PRs require passing tests before the PR will be reviewed. 60 | 61 | All test files are in the [`test`](test) directory. 62 | 63 | For the purposes of contributing to this repo, please update the [`test.rb`](test/test.rb) file with unit tests as you modify the code. 64 | 65 | To run the tests: 66 | 67 | ```bash 68 | rake test 69 | ``` 70 | 71 | 72 | ## Style Guidelines & Naming Conventions 73 | 74 | Generally, we follow the style guidelines as suggested by the official language. However, we ask that you conform to the styles that already exist in the library. If you wish to deviate, please explain your reasoning. 75 | 76 | - [Community Driven Style Guide](https://github.com/bbatsov/ruby-style-guide) 77 | 78 | Please run your code through: 79 | 80 | - [rubocop](https://github.com/bbatsov/rubocop). 81 | 82 | ## Creating a Pull Request 83 | 84 | 1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, 85 | and configure the remotes: 86 | 87 | ```bash 88 | # Clone your fork of the repo into the current directory 89 | git clone https://github.com/sendgrid/smtpapi-ruby 90 | # Navigate to the newly cloned directory 91 | cd smtpapi-ruby 92 | # Assign the original repo to a remote called "upstream" 93 | git remote add upstream https://github.com/sendgrid/smtpapi-ruby 94 | ``` 95 | 96 | 2. If you cloned a while ago, get the latest changes from upstream: 97 | 98 | ```bash 99 | git checkout 100 | git pull upstream 101 | ``` 102 | 103 | 3. Create a new topic branch (off the main project development branch) to 104 | contain your feature, change, or fix: 105 | 106 | ```bash 107 | git checkout -b 108 | ``` 109 | 110 | 4. Commit your changes in logical chunks. Please adhere to these [git commit 111 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 112 | or your code is unlikely to be merged into the main project. Use Git's 113 | [interactive rebase](https://help.github.com/articles/interactive-rebase) 114 | feature to tidy up your commits before making them public. 115 | 116 | 4a. Create tests. 117 | 118 | 4b. Create or update the example code that demonstrates the functionality of this change to the code. 119 | 120 | 5. Locally merge (or rebase) the upstream development branch into your topic branch: 121 | 122 | ```bash 123 | git pull [--rebase] upstream main 124 | ``` 125 | 126 | 6. Push your topic branch up to your fork: 127 | 128 | ```bash 129 | git push origin 130 | ``` 131 | 132 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) 133 | with a clear title and description against the `main` branch. All tests must be passing before we will review the PR. 134 | 135 | 136 | ## Code Reviews 137 | 138 | If you can, please look at open PRs and review them. Give feedback and help us merge these PRs much faster! If you don't know how, Github has some great information on how to review a Pull Request. 139 | -------------------------------------------------------------------------------- /test/test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'test/unit' 3 | require './lib/smtpapi' 4 | 5 | # 6 | # SmtpapiTest implementation 7 | # 8 | class SmtpapiTest < Test::Unit::TestCase 9 | def test_version 10 | assert_equal('0.1.12', Smtpapi::VERSION) 11 | end 12 | 13 | def test_empty 14 | header = Smtpapi::Header.new 15 | assert_equal('{}', header.json_string) 16 | end 17 | 18 | def test_add_to 19 | header = Smtpapi::Header.new 20 | header.add_to('you@youremail.com') 21 | header.add_to('other@otheremail.com', 'Other Name') 22 | assert_equal( 23 | '{"to":["you@youremail.com","Other Name "]}', 24 | header.json_string 25 | ) 26 | end 27 | 28 | def test_add_to_array 29 | header = Smtpapi::Header.new 30 | header.add_to(['you@youremail.com', 'my@myemail.com']) 31 | assert_equal( 32 | '{"to":["you@youremail.com","my@myemail.com"]}', 33 | header.json_string 34 | ) 35 | end 36 | 37 | def test_set_tos 38 | header = Smtpapi::Header.new 39 | header.set_tos(['you@youremail.com', 'other@otheremail.com']) 40 | assert_equal( 41 | '{"to":["you@youremail.com","other@otheremail.com"]}', 42 | header.json_string 43 | ) 44 | end 45 | 46 | def test_add_substitution 47 | header = Smtpapi::Header.new 48 | header.add_substitution('keep', ['secret']) 49 | header.add_substitution('other', %w(one two)) 50 | assert_equal( 51 | '{"sub":{"keep":["secret"],"other":["one","two"]}}', 52 | header.json_string 53 | ) 54 | end 55 | 56 | def test_set_substitutions 57 | header = Smtpapi::Header.new 58 | header.set_substitutions('keep' => ['secret']) 59 | assert_equal('{"sub":{"keep":["secret"]}}', header.json_string) 60 | end 61 | 62 | def test_add_section 63 | header = Smtpapi::Header.new 64 | header.add_section('-charge-', 'This ship is useless.') 65 | header.add_section('-bomber-', 'Only for sad vikings.') 66 | assert_equal( 67 | '{"section":'\ 68 | '{"-charge-":"This ship is useless.",'\ 69 | '"-bomber-":"Only for sad vikings."}}', 70 | header.json_string 71 | ) 72 | end 73 | 74 | def test_set_sections 75 | header = Smtpapi::Header.new 76 | header.set_sections('-charge-' => 'This ship is useless.') 77 | assert_equal( 78 | '{"section":{"-charge-":"This ship is useless."}}', 79 | header.json_string 80 | ) 81 | end 82 | 83 | def test_add_unique_arg 84 | header = Smtpapi::Header.new 85 | header.add_unique_arg('cat', 'dogs') 86 | assert_equal('{"unique_args":{"cat":"dogs"}}', header.json_string) 87 | end 88 | 89 | def test_set_unique_args 90 | header = Smtpapi::Header.new 91 | header.set_unique_args('cow' => 'chicken') 92 | header.set_unique_args('dad' => 'proud') 93 | assert_equal('{"unique_args":{"dad":"proud"}}', header.json_string) 94 | end 95 | 96 | def test_add_category 97 | header = Smtpapi::Header.new 98 | header.add_category('tactics') 99 | header.add_category('advanced') 100 | assert_equal('{"category":["tactics","advanced"]}', header.json_string) 101 | end 102 | 103 | def test_set_categories 104 | header = Smtpapi::Header.new 105 | header.set_categories(%w(tactics advanced)) 106 | assert_equal('{"category":["tactics","advanced"]}', header.json_string) 107 | end 108 | 109 | def test_add_filter 110 | header = Smtpapi::Header.new 111 | header.add_filter('footer', 'enable', 1) 112 | header.add_filter('footer', 'text/html', 'boo') 113 | assert_equal( 114 | '{"filters":'\ 115 | '{"footer":'\ 116 | '{"settings":'\ 117 | '{"enable":1,'\ 118 | '"text/html":"boo"'\ 119 | '}'\ 120 | '}'\ 121 | '}'\ 122 | '}', 123 | header.json_string 124 | ) 125 | end 126 | 127 | def test_set_filters 128 | header = Smtpapi::Header.new 129 | filter = { 130 | 'footer' => { 131 | 'setting' => { 132 | 'enable' => 1, 133 | 'text/plain' => 'You can haz footers!' 134 | } 135 | } 136 | } 137 | header.set_filters(filter) 138 | assert_equal( 139 | '{"filters":'\ 140 | '{"footer":'\ 141 | '{"setting":'\ 142 | '{"enable":1,"text/plain":"You can haz footers!"}'\ 143 | '}'\ 144 | '}'\ 145 | '}', 146 | header.json_string 147 | ) 148 | end 149 | 150 | def test_add_category_unicode 151 | header = Smtpapi::Header.new 152 | header.add_category('Martí') 153 | header.add_category('天破活殺') 154 | header.add_category('天翔十字鳳') 155 | assert_equal( 156 | '{"category":'\ 157 | '["Mart\\u00ed",'\ 158 | '"\\u5929\\u7834\\u6d3b\\u6bba",'\ 159 | '"\\u5929\\u7fd4\\u5341\\u5b57\\u9cf3"]}', 160 | header.json_string 161 | ) 162 | header.add_category('鼖') 163 | assert_equal( 164 | '{"category":'\ 165 | '["Mart\\u00ed",'\ 166 | '"\\u5929\\u7834\\u6d3b\\u6bba",'\ 167 | '"\\u5929\\u7fd4\\u5341\\u5b57\\u9cf3",'\ 168 | '"\\ud87e\\ude1b"]}', 169 | header.json_string 170 | ) 171 | end 172 | 173 | def test_sent_send_at 174 | header = Smtpapi::Header.new 175 | localtime = Time.local(2014, 8, 29, 17, 56, 35) 176 | header.set_send_at(localtime) 177 | 178 | assert_equal("{\"send_at\":#{localtime.to_i}}", header.json_string) 179 | end 180 | 181 | def test_send_each_at 182 | header = Smtpapi::Header.new 183 | localtime1 = Time.local(2014, 8, 29, 17, 56, 35) 184 | localtime2 = Time.local(2013, 12, 31, 0, 0, 0) 185 | localtime3 = Time.local(2015, 9, 1, 4, 5, 6) 186 | header.set_send_each_at([localtime1, localtime2, localtime3]) 187 | 188 | assert_equal( 189 | '{"send_each_at":'\ 190 | "[#{localtime1.to_i},#{localtime2.to_i},#{localtime3.to_i}]"\ 191 | '}', 192 | header.json_string 193 | ) 194 | end 195 | 196 | def test_asm_group_id 197 | header = Smtpapi::Header.new 198 | header.set_asm_group(2) 199 | 200 | assert_equal('{"asm_group_id":2}', header.json_string) 201 | end 202 | 203 | def test_ip_pool 204 | header = Smtpapi::Header.new 205 | header.set_ip_pool('test_pool') 206 | 207 | assert_equal('{"ip_pool":"test_pool"}', header.json_string) 208 | end 209 | 210 | # def test_docker_exists 211 | # assert(File.file?('./Dockerfile') || File.file?('./docker/Dockerfile')) 212 | # end 213 | 214 | # def test_docker_compose_exists 215 | # assert( 216 | # File.file?('./docker-compose.yml') || 217 | # File.file?('./docker/docker-compose.yml') 218 | # ) 219 | # end 220 | 221 | def test_env_sample_exists 222 | assert(File.file?('./.env_sample')) 223 | end 224 | 225 | def test_gitignore_exists 226 | assert(File.file?('./.gitignore')) 227 | end 228 | 229 | def test_github_actions_exists 230 | assert(File.file?('./.github/workflows/test-and-deploy.yml')) 231 | end 232 | 233 | def test_changelog_exists 234 | assert(File.file?('./CHANGELOG.md')) 235 | end 236 | 237 | def test_code_of_conduct_exists 238 | assert(File.file?('./CODE_OF_CONDUCT.md')) 239 | end 240 | 241 | def test_contributing_exists 242 | assert(File.file?('./CONTRIBUTING.md')) 243 | end 244 | 245 | def test_license_exists 246 | assert(File.file?('./LICENSE')) 247 | end 248 | 249 | def test_pull_request_template_exists 250 | assert(File.file?('./PULL_REQUEST_TEMPLATE.md')) 251 | end 252 | 253 | def test_readme_exists 254 | assert(File.file?('./README.md')) 255 | end 256 | 257 | def test_troubleshooting_exists 258 | assert(File.file?('./TROUBLESHOOTING.md')) 259 | end 260 | 261 | # def test_usage_exists 262 | # assert(File.file?('./USAGE.md')) 263 | # end 264 | 265 | # def test_use_cases_exists 266 | # assert(File.file?('./USE_CASES.md')) 267 | # end 268 | 269 | def test_license_date_is_updated 270 | license_year = IO.read('LICENSE').match( 271 | /Copyright \(C\) (\d{4}), Twilio SendGrid/ 272 | )[1] 273 | current_year = Time.new.year 274 | 275 | assert_equal(current_year, license_year.to_i) 276 | end 277 | end 278 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | This project adheres to [Semantic Versioning](http://semver.org/). 5 | 6 | [2022-03-09] Version 0.1.12 7 | --------------------------- 8 | **Library - Chore** 9 | - [PR #102](https://github.com/sendgrid/smtpapi-ruby/pull/102): push Datadog Release Metric upon deploy success. Thanks to [@eshanholtz](https://github.com/eshanholtz)! 10 | 11 | 12 | [2022-02-09] Version 0.1.11 13 | --------------------------- 14 | **Library - Chore** 15 | - [PR #101](https://github.com/sendgrid/smtpapi-ruby/pull/101): upgrade supported language versions. Thanks to [@childish-sambino](https://github.com/childish-sambino)! 16 | - [PR #100](https://github.com/sendgrid/smtpapi-ruby/pull/100): add gh release to workflow. Thanks to [@shwetha-manvinkurke](https://github.com/shwetha-manvinkurke)! 17 | - [PR #99](https://github.com/sendgrid/smtpapi-ruby/pull/99): migrate to gh actions. Thanks to [@beebzz](https://github.com/beebzz)! 18 | 19 | 20 | [2022-01-12] Version 0.1.10 21 | --------------------------- 22 | **Library - Chore** 23 | - [PR #98](https://github.com/sendgrid/smtpapi-ruby/pull/98): update license year. Thanks to [@JenniferMah](https://github.com/JenniferMah)! 24 | 25 | 26 | [2020-09-02] Version 0.1.9 27 | -------------------------- 28 | **Library - Chore** 29 | - [PR #71](https://github.com/sendgrid/smtpapi-ruby/pull/71): Conformance To Style Standards With RuboCop & TravisCI. Thanks to [@alanunruh](https://github.com/alanunruh)! 30 | 31 | 32 | [2020-08-19] Version 0.1.8 33 | -------------------------- 34 | **Library - Docs** 35 | - [PR #72](https://github.com/sendgrid/smtpapi-ruby/pull/72): Update *.md files using Grammarly. Thanks to [@anatolyyyyyy](https://github.com/anatolyyyyyy)! 36 | 37 | **Library - Chore** 38 | - [PR #96](https://github.com/sendgrid/smtpapi-ruby/pull/96): update GitHub branch references to use HEAD. Thanks to [@thinkingserious](https://github.com/thinkingserious)! 39 | 40 | 41 | [2020-08-05] Version 0.1.7 42 | -------------------------- 43 | **Library - Chore** 44 | - [PR #36](https://github.com/sendgrid/smtpapi-ruby/pull/36): fix CodeClimate suggestions. Thanks to [@valterbarros](https://github.com/valterbarros)! 45 | 46 | 47 | [2020-07-22] Version 0.1.6 48 | -------------------------- 49 | **Library - Docs** 50 | - [PR #82](https://github.com/sendgrid/smtpapi-ruby/pull/82): Create usage.md file. Thanks to [@prathamsharma92](https://github.com/prathamsharma92)! 51 | - [PR #83](https://github.com/sendgrid/smtpapi-ruby/pull/83): add code review section in contributions. Thanks to [@prathamsharma92](https://github.com/prathamsharma92)! 52 | 53 | 54 | [2020-03-04] Version 0.1.5 55 | -------------------------- 56 | **Library - Chore** 57 | - [PR #95](https://github.com/sendgrid/smtpapi-ruby/pull/95): add Ruby 2.7 to Travis. Thanks to [@childish-sambino](https://github.com/childish-sambino)! 58 | 59 | 60 | [2020-02-19] Version 0.1.4 61 | -------------------------- 62 | **Library - Chore** 63 | - [PR #87](https://github.com/sendgrid/smtpapi-ruby/pull/87): Add test coverage analysis. Thanks to [@RolandBurrows](https://github.com/RolandBurrows)! 64 | 65 | 66 | [2020-01-22] Version 0.1.3 67 | -------------------------- 68 | **Library - Fix** 69 | - [PR #94](https://github.com/sendgrid/smtpapi-ruby/pull/94): add skip_cleanup flag to fix travis deploy. Thanks to [@thinkingserious](https://github.com/thinkingserious)! 70 | 71 | 72 | [2020-01-22] Version 0.1.2 73 | -------------------------- 74 | **Library - Docs** 75 | - [PR #93](https://github.com/sendgrid/smtpapi-ruby/pull/93): baseline all the templated markdown docs. Thanks to [@childish-sambino](https://github.com/childish-sambino)! 76 | 77 | 78 | [2020-01-09] Version 0.1.1 79 | -------------------------- 80 | **Library - Chore** 81 | - [PR #92](https://github.com/sendgrid/smtpapi-ruby/pull/92): Auto-deploy upon successful tagged commit. Thanks to [@thinkingserious](https://github.com/thinkingserious)! 82 | - [PR #50](https://github.com/sendgrid/smtpapi-ruby/pull/50): Update License date range. Thanks to [@shucon](https://github.com/shucon)! 83 | - [PR #85](https://github.com/sendgrid/smtpapi-ruby/pull/85): updated Readme.md. Thanks to [@rahulpuroht](https://github.com/rahulpuroht)! 84 | - [PR #67](https://github.com/sendgrid/smtpapi-ruby/pull/67): Add Use Cases directory. Thanks to [@eyewritecode](https://github.com/eyewritecode)! 85 | - [PR #65](https://github.com/sendgrid/smtpapi-ruby/pull/65): Update LICENSE.txt. Thanks to [@nocategory](https://github.com/nocategory)! 86 | - [PR #64](https://github.com/sendgrid/smtpapi-ruby/pull/64): Resolve linting issues. Thanks to [@mrala](https://github.com/mrala)! 87 | - [PR #46](https://github.com/sendgrid/smtpapi-ruby/pull/46): Replaced .length > 0 with .!empty?. Thanks to [@nvzard](https://github.com/nvzard)! 88 | - [PR #35](https://github.com/sendgrid/smtpapi-ruby/pull/35): Replaced .length > 0 with !empty #32. Thanks to [@181514912](https://github.com/181514912)! 89 | - [PR #42](https://github.com/sendgrid/smtpapi-ruby/pull/42): Added unittest to check for specific repo files. Thanks to [@mptap](https://github.com/mptap)! 90 | - [PR #40](https://github.com/sendgrid/smtpapi-ruby/pull/40): Update LICENSE.txt. Thanks to [@GaryLeutheuser](https://github.com/GaryLeutheuser)! 91 | - [PR #41](https://github.com/sendgrid/smtpapi-ruby/pull/41): Add License end year test. Thanks to [@diegous](https://github.com/diegous)! 92 | - [PR #43](https://github.com/sendgrid/smtpapi-ruby/pull/43): Update LICENSE.txt. Thanks to [@astromoose](https://github.com/astromoose)! 93 | - [PR #26](https://github.com/sendgrid/smtpapi-ruby/pull/26): add a .env_sample file. Thanks to [@thepriefy](https://github.com/thepriefy)! 94 | - [PR #24](https://github.com/sendgrid/smtpapi-ruby/pull/24): add Gem badge to README file. Thanks to [@thepriefy](https://github.com/thepriefy)! 95 | - [PR #28](https://github.com/sendgrid/smtpapi-ruby/pull/28): Added the gem badge. Thanks to [@roooodcastro](https://github.com/roooodcastro)! 96 | - [PR #44](https://github.com/sendgrid/smtpapi-ruby/pull/44): Rename PULL_REQUEST_TEMPLATE.md. Thanks to [@thepriefy](https://github.com/thepriefy)! 97 | - [PR #25](https://github.com/sendgrid/smtpapi-ruby/pull/25): add pull request template. Thanks to [@rohitdaryanani](https://github.com/rohitdaryanani)! 98 | - [PR #31](https://github.com/sendgrid/smtpapi-ruby/pull/31): Added .codeclimate.yml. Thanks to [@veruz](https://github.com/veruz)! 99 | - [PR #18](https://github.com/sendgrid/smtpapi-ruby/pull/18): add .github/ISSUE_TEMPLATE. Thanks to [@thepriefy](https://github.com/thepriefy)! 100 | - [PR #13](https://github.com/sendgrid/smtpapi-ruby/pull/13): Add/update badges on README. Thanks to [@jessecalton](https://github.com/jessecalton)! 101 | - [PR #12](https://github.com/sendgrid/smtpapi-ruby/pull/12): more SEO friendly url. Thanks to [@ladhadha](https://github.com/ladhadha)! 102 | 103 | **Library - Fix** 104 | - [PR #69](https://github.com/sendgrid/smtpapi-ruby/pull/69): Remove duplicate text in CONTRIBUTING.md. Thanks to [@eyewritecode](https://github.com/eyewritecode)! 105 | - [PR #17](https://github.com/sendgrid/smtpapi-ruby/pull/17): Fixed some Grammatical errors in CONTRIBUTING.md. Thanks to [@mohsincl](https://github.com/mohsincl)! 106 | - [PR #16](https://github.com/sendgrid/smtpapi-ruby/pull/16): update contributing and readme - fix typo and ToC. Thanks to [@pushkyn](https://github.com/pushkyn)! 107 | 108 | **Library - Docs** 109 | - [PR #15](https://github.com/sendgrid/smtpapi-ruby/pull/15): update README.md. Thanks to [@thepriefy](https://github.com/thepriefy)! 110 | - [PR #14](https://github.com/sendgrid/smtpapi-ruby/pull/14): add table of contents in README.md. Thanks to [@thepriefy](https://github.com/thepriefy)! 111 | - [PR #9](https://github.com/sendgrid/smtpapi-ruby/pull/9): Add TROUBLESHOOTING.md. Thanks to [@colto](https://github.com/colto)! 112 | - [PR #7](https://github.com/sendgrid/smtpapi-ruby/pull/7): Added Code of Conduct. Thanks to [@gr8shivam](https://github.com/gr8shivam)! 113 | - [PR #5](https://github.com/sendgrid/smtpapi-ruby/pull/5): Update README.md. Thanks to [@ciceropablo](https://github.com/ciceropablo)! 114 | 115 | 116 | [2015-04-06] Version 0.1.0 117 | -------------------------- 118 | ### Changed 119 | - Change home to SendGrid 120 | - Add unit test dev dep 121 | --------------------------------------------------------------------------------