SendGrid - NoMethodError (méthode `[]' indéfinie pour nil:NilClass)

Bonjour,

J’ai commencé à utiliser le webhook SendGrid avec une clé de vérification. Je reçois maintenant beaucoup de ces erreurs. J’ai envoyé une invitation en masse avec SendGrid.

app/controllers/webhooks_controller.rb:29:in `block in sendgrid'
app/controllers/webhooks_controller.rb:24:in `each'
app/controllers/webhooks_controller.rb:24:in `sendgrid'
actionpack (7.0.7) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (7.0.7) lib/abstract_controller/base.rb:215:in `process_action'
actionpack (7.0.7) lib/action_controller/metal/rendering.rb:165:in `process_action'
actionpack (7.0.7) lib/abstract_controller/callbacks.rb:234:in `block in process_action'
activesupport (7.0.7) lib/active_support/callbacks.rb:107:in `run_callbacks'
actionpack (7.0.7) lib/abstract_controller/callbacks.rb:233:in `process_action'
actionpack (7.0.7) lib/action_controller/metal/rescue.rb:23:in `process_action'
actionpack (7.0.7) lib/action_controller/metal/instrumentation.rb:67:in `block in process_action'
activesupport (7.0.7) lib/active_support/notifications.rb:206:in `block in instrument'
activesupport (7.0.7) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activesupport (7.0.7) lib/active_support/notifications.rb:206:in `instrument'
actionpack (7.0.7) lib/action_controller/metal/instrumentation.rb:66:in `process_action'
actionpack (7.0.7) lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
activerecord (7.0.7) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
actionpack (7.0.7) lib/abstract_controller/base.rb:151:in `process'
actionview (7.0.7) lib/action_view/rendering.rb:39:in `process'
rack-mini-profiler (3.1.1) lib/mini_profiler/profiling_methods.rb:85:in `block in profile_method'
actionpack (7.0.7) lib/action_controller/metal.rb:188:in `dispatch'
actionpack (7.0.7) lib/action_controller/metal.rb:251:in `dispatch'
actionpack (7.0.7) lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
actionpack (7.0.7) lib/action_dispatch/routing/route_set.rb:32:in `serve'
actionpack (7.0.7) lib/action_dispatch/journey/router.rb:50:in `block in serve'
actionpack (7.0.7) lib/action_dispatch/journey/router.rb:32:in `each'
actionpack (7.0.7) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (7.0.7) lib/action_dispatch/routing/route_set.rb:852:in `call'
lib/middleware/omniauth_bypass_middleware.rb:64:in `call'
rack (2.2.8) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.8) lib/rack/conditional_get.rb:40:in `call'
rack (2.2.8) lib/rack/head.rb:12:in `call'
actionpack (7.0.7) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/anonymous_cache.rb:389:in `call'
lib/middleware/gtm_script_nonce_injector.rb:10:in `call'
rack (2.2.8) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.8) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/cookies.rb:704:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (7.0.7) lib/active_support/callbacks.rb:99:in `run_callbacks'
actionpack (7.0.7) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/debug_exceptions.rb:28:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/show_exceptions.rb:29:in `call'
logster (2.13.1) lib/logster/middleware/reporter.rb:40:in `call'
railties (7.0.7) lib/rails/rack/logger.rb:40:in `call_app'
railties (7.0.7) lib/rails/rack/logger.rb:27:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/remote_ip.rb:93:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/request_id.rb:26:in `call'
lib/middleware/enforce_hostname.rb:24:in `call'
rack (2.2.8) lib/rack/method_override.rb:24:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/executor.rb:14:in `call'
rack (2.2.8) lib/rack/sendfile.rb:110:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/host_authorization.rb:131:in `call'
rack-mini-profiler (3.1.1) lib/mini_profiler.rb:260:in `call'
message_bus (4.3.8) lib/message_bus/rack/middleware.rb:60:in `call'
lib/middleware/request_tracker.rb:233:in `call'
railties (7.0.7) lib/rails/engine.rb:530:in `call'
railties (7.0.7) lib/rails/railtie.rb:226:in `public_send'
railties (7.0.7) lib/rails/railtie.rb:226:in `method_missing'
rack (2.2.8) lib/rack/urlmap.rb:74:in `block in call'
rack (2.2.8) lib/rack/urlmap.rb:58:in `each'
rack (2.2.8) lib/rack/urlmap.rb:58:in `call'
unicorn (6.1.0) lib/unicorn/http_server.rb:634:in `process_client'
unicorn (6.1.0) lib/unicorn/http_server.rb:739:in `worker_loop'
unicorn (6.1.0) lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
unicorn (6.1.0) lib/unicorn/http_server.rb:143:in `start'
unicorn (6.1.0) bin/unicorn:128:in `<top (required)>'
vendor/bundle/ruby/3.2.0/bin/unicorn:25:in `load'
vendor/bundle/ruby/3.2.0/bin/unicorn:25:in `<main>'

ENV

|REQUEST_URI|/webhooks/sendgrid|
|REQUEST_METHOD|POST|
|HTTP_USER_AGENT|SendGrid Event API|

Cela semble être le même problème qu’ici, qui était un bug corrigé il y a quelque temps : Sendgrid error: NoMethodError (undefined method `[]' for nil:NilClass) - #3 by Terrapop

Ceux-ci sont générés pour les rebonds de votre liste qui ne sont pas des utilisateurs de discourse ?

Je ne suis pas sûr s’il s’agit de rebonds, comment pourrions-nous vérifier ? C’est très probablement autour du moment où nous avons effectué une invitation en masse à des utilisateurs n’utilisant pas Discourse.

Il se peut que quelque chose ne fonctionne pas avec la charge utile de l’événement reçue de Sendgrid. Il semble que le status ne soit pas défini sur les événements bounce comme prévu.

En supposant que vous ayez obtenu la trace de la pile de logster à \u003cYOUR_SITE\u003e/logs, l’onglet env devrait contenir les détails de la requête. Pourriez-vous fournir une copie désinfectée de la charge utile à partir de là ?

Il n’y a pas beaucoup d’informations là-dedans, la plupart que j’ai mises ici.

Pour la référence complète, je l’ai mise ci-dessous comme demandé

hostname serverhostname
process_id 248749
application_version a8d6dc4d3a5c3d937ff0bb162c93ec628428cda1
HTTP_HOST forum.URL.co.uk
REQUEST_URI /webhooks/sendgrid
REQUEST_METHOD POST
HTTP_USER_AGENT SendGrid Event API
HTTP_X_FORWARDED_FOR IPADDRESS
HTTP_X_REAL_IP IPADDRESS
time Di 17:54

Je suis désolé, j’aurais dû être plus précis. Le corps de la requête contient les indices nécessaires. Vous devriez pouvoir le trouver après la ligne time. Vous devrez peut-être faire défiler vers le haut ou développer le panneau pour le voir.

Bonjour,

Il n’y a pas d’informations supplémentaires après la ligne Time, j’ai vérifié les 34 erreurs. Cela semble étrange, mais pourquoi n’est-ce pas inclus ?

Oui, c’est étrange. Pourriez-vous plutôt récupérer la charge utile du tableau de bord SendGrid ?

Selon la dernière documentation des webhooks SendGrid, le point de terminaison actuel dans Discourse devrait fonctionner sans problème, mais l’erreur pointe vers un problème avec la charge utile de la requête, donc un exemple serait formidable.

Avez-vous déjà résolu ce problème ? J’ai la même erreur, sur la même ligne de code :

Je ne connais pas Ruby, mais il semble qu’il puisse analyser le JSON sans problème jusqu’à ce qu’il essaie d’analyser le code d’erreur, Email::SMTP_STATUS_TRANSIENT_FAILURE pointe vers :

J’ai vérifié sur Webhook.site ce que Sendgrid envoie réellement lorsque je teste le webhook, et cela ressemble à ceci pour un rebond :

[
  {
    "email": "example@test.com",
    "timestamp": 1740136261,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-555>",
    "event": "bounce",
    "category": [
      "cat facts"
    ],
    "sg_event_id": "ovGQ2rRo8ytNezHPDq-7Ig==",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B88.0",
    "reason": "500 unknown recipient",
    "status": "5.0.0"
  }
]

On dirait que ça devrait fonctionner !

Aha.. je réponds à ma propre question, le bouton « Tester l’intégration » du Webhook vous ment..

Voici la charge utile réelle si j’envoie réellement un e-mail à une adresse e-mail inexistante :

[
  {
    "bounce_classification": "Non classifié",
    "email": "noemail@this.does.not.exist.tld",
    "event": "bounce",
    "reason": "impossible d'obtenir les informations mx : échec de l'obtention des adresses IP à partir de l'enregistrement PTR : recherche <nil> : adresse non reconnue",
    "sg_event_id": "Ym91bmNlLTQtNTA0ODUxOTUtZXVvMmlLeGRTYXlQRjRZRTQtLUk3QS0w",
    "sg_message_id": "euo2iKxdSayPF4YE4--I7A.recvd-5f54b5d587-pczjm-1-67BADEEA-6.0",
    "smtp-id": "<870b3a2a-160c-4fc8-bc9a-bd0d5b943b81@forum.umbraco.com>",
    "timestamp": 1740300320,
    "tls": 0,
    "type": "blocked"
  }
]

Et voilà : pas de champ status.

C’est lorsque j’utilise délibérément un domaine qui n’existe pas, j’ai l’impression que cela devrait être géré, peut-être que \"type\": \"blocked\" peut être l’indicateur que Discourse recherche.

Comme autre tentative, j’ai mis quelque chose d’absurde devant outlook.com et cela me donne une charge utile fonctionnelle :

[
  {
    "bounce_classification": "Adresse invalide",
    "email": "oeihoiwehitwiohtriuweruiwerwierhwuerguiwerg@outlook.com",
    "event": "bounce",
    "ip": "149.72.1.78",
    "reason": "550 5.5.0 Action demandée non effectuée : boîte aux lettres indisponible (S2017062302). [HK3PEPF0000021E.apcprd03.prod.outlook.com 2025-02-23T08:54:35.950Z 08DD502499E1A0AA]",
    "sg_event_id": "Ym91bmNlLTAtNTA0ODUxOTUtQWJFZ2pVejZUUFd3MnJNTnJabDg4Zy0w",
    "sg_message_id": "AbEgjUz6TPWw2rMNrZl88g.recvd-786d47b7ff-tsp86-1-67BAE249-D.0",
    "smtp-id": "<d8dc253e-6e9a-4418-8478-60780eb4898c@forum.umbraco.com>",
    "status": "5.5.0",
    "timestamp": 1740300876,
    "tls": 1,
    "type": "bounce"
  }
]

J’ai fait une PR !

@cultiv Merci d’avoir étudié le problème et pris le temps de soumettre une PR. J’ai utilisé votre PR comme base et fusionné un correctif pour le problème dans FIX: No method error in `WebhooksController#sendgrid` (#31495) · discourse/discourse@209d289 · GitHub.

2 « J'aime »

Fantastique, c’était très utile. Je n’aurais pas pu faire tout ça tout seul :sweat_smile:

Merci, j’ai mis à jour et un test manuel fonctionne maintenant correctement, le journal d’erreurs est propre et je peux voir le rebond de l’e-mail dans le journal de messagerie :raising_hands:

1 « J'aime »