tilleuls/ymlp-bundle
A Symfony bundle for integrating the YMLP (Your Mailing List Provider) API. It provides configuration and service classes to manage mailing lists, subscribers, and newsletter-related operations directly from Symfony applications.
This bundle is a thin Symfony wrapper around YMLP's legacy PHP client (YMLP_API). It was released in March 2017, targets Symfony 2.x/3.x, and has almost no downstream usage — so treat it as a reference integration rather than a maintained dependency. First steps:
composer require tilleuls/ymlp-bundle
app/AppKernel.php (the pre-Symfony 4 way):
new CoopTilleuls\Bundle\YmlpBundle\CoopTilleulsYmlpBundle(),
config.yml. YMLP uses a triple of username, password, and an API key:
coop_tilleuls_ymlp:
username: "%ymlp_user%"
password: "%ymlp_password%"
key: "%ymlp_key%"
format: json # json | php | xml
DependencyInjection/Configuration.php and the service definition in Resources/config/services.xml. The API entry point is the service that wraps YMLP_API — inject that, don't instantiate YMLP_API yourself.$ymlp->AddContact('newsletter', $email, $fields, $group, $unsubscribe, $overwrite);
If you have no strong reason to keep this exact bundle, jump straight to Gotchas and Tips before writing code — you will likely want to vendor a fresh API client and wrap it yourself.
Service injection over static calls. Do not call YMLP_API statically from controllers. Inject the bundle's service (or an alias) into a dedicated NewsletterManager / Subscriber domain service so you can swap it out and mock it in tests.
Wrap the raw API in your own interface. The YMLP methods are cryptic (AddContact, DeleteContact, GetContact, ListContacts, AddGroup, GetGroups, GetLists, GetFields, Unsubscribe, etc.) and take long positional argument lists. A small interface like:
interface NewsletterSubscriber {
public function subscribe(string $email, string $list): void;
public function unsubscribe(string $email, string $list): void;
}
pays for itself the moment you replace YMLP or add a second provider.
Subscription flow. Typical day-to-day pattern:
AddContact($listName, $email, $fields, $group, false, true) — the last overwrite flag controls whether an existing contact is updated instead of erroring.Subscriber row with the YMLP ID so you can reconcile later with GetContact/ListContacts.Bulk and maintenance operations. Use ListContacts / GetContacts for sync jobs. Run them as a Symfony command (app/console ymlp:sync) rather than inside a web request — the YMLP API returns large payloads slowly. For anything above a few hundred contacts, paginate and queue.
Error handling. The legacy client returns arrays with an Code and Output key; success is Code === 0. Wrap calls in a try/catch, map non-zero codes to your own exceptions, and log the raw Output for support tickets.
Testing. Mock the injected service in functional tests; never let unit tests hit the YMLP endpoint. Integration tests should be tagged @group external and skipped in CI unless you have sandbox credentials.
Configuration as feature flags. If YMLP is one of several newsletter backends for you, add a simple newsletter.driver parameter and register the YMLP service under a conditional tag so switching is a config change rather than a code change.
Package is abandoned). For new work, use a modern client (e.g. a hand-rolled Guzzle client or a maintained YMLP SDK) behind your own interface.services.yaml, no Symfony\Flex recipe. You register the bundle in AppKernel and configure in config.yml. Migrating to Symfony 4+ means either keeping AppKernel compatibility or re-registering the bundle manually and aliasing the service by hand.username, password, and key from parameters. Keep them in .env, never in config.yml committed to git.format: json is the sane default; the php format returns serialized arrays and will bite you if you json_decode. Set the format explicitly once and keep it consistent.AddContact(listName, email, fields, group, unsubscribe, overwrite) and similar methods are easy to mis-order. Wrap them so callers pass named arguments.ListContacts/GetContacts calls can be slow. Set a sensible Guzzle timeout if you replace the client, and paginate lists rather than dumping everything.Psr\Log\LoggerInterface so failed API responses land in your normal logs.YMLP_API subclass or HTTP client. There's no event system, no plugin hooks, no compiler pass worth using.How can I help you explore Laravel packages today?